Sat Mar 10 01:54:50 2012

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 <sys/stat.h>
#include <math.h>
#include <ctype.h>
#include <dahdi/user.h>
#include <dahdi/tonezone.h>
#include "sig_analog.h"
#include "sig_pri.h"
#include "sig_ss7.h"
#include <openr2.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/cel.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 "asterisk/ccss.h"
#include "asterisk/data.h"

Go to the source code of this file.

Data Structures

struct  dahdi_chan_conf
 Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section of chan_dahdi.conf. Generally there is a field here for every possible configuration item. More...
struct  dahdi_distRings
struct  dahdi_mfcr2
struct  dahdi_mfcr2_conf
struct  dahdi_parms_pseudo
struct  dahdi_pri
struct  dahdi_pvt
struct  dahdi_ss7
struct  dahdi_starting_point
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 CALLWAITING_SUPPRESS_SAMPLES   ((100 * 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 CHAN_TAG   "Chan "
#define CIDCW_EXPIRE_SAMPLES   ((500 * 8) / READ_SIZE)
#define CONF_USER_REAL   (1 << 0)
#define CONF_USER_THIRDCALL   (1 << 1)
#define CONTEXT_TAG   "Context - "
#define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
#define DATA_EXPORT_DAHDI_PVT(MEMBER)
#define DEFAULT_CIDRINGS   1
 Typically, how many rings before we should send Caller*ID.
#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 FORMAT   "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
#define FORMAT   "%4s %40s\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)->channel)
#define HANGUP   1
#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)
#define HEADER_MS   50
#define ISTRUNK(p)
#define MASK_AVAIL   (1 << 0)
#define MASK_INUSE   (1 << 1)
#define MAX_CHANLIST_LEN   80
#define MAX_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_SPANS   32
#define POLARITY_IDLE   0
#define POLARITY_REV   1
#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)
#define PROC_DAHDI_OPT_NOWARN   (1 << 1)
#define R2_LINK_CAPACITY   10
#define READ_SIZE   160
#define REPORT_CHANNEL_ALARMS   1
#define REPORT_SPAN_ALARMS   2
#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_MFCR2   DAHDI_SIG_CAS
#define SIG_MFCR2_MAX_CHANNELS   672
#define SIG_PRI   DAHDI_SIG_CLEAR
#define SIG_PRI_LIB_HANDLE_CASES
#define SIG_SF   DAHDI_SIG_SF
#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)
#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)
#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
#define SIG_SS7   (0x1000000 | DAHDI_SIG_CLEAR)
#define SMDI_MD_WAIT_TIMEOUT   1500
#define SUB_CALLWAIT   1
#define SUB_REAL   0
#define SUB_THREEWAY   2
#define TRAILER_MS   5
#define TRANSFER   0

Enumerations

enum  DAHDI_IFLIST { DAHDI_IFLIST_NONE, DAHDI_IFLIST_MAIN, DAHDI_IFLIST_NO_B_CHAN }
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 _dahdi_get_index (struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
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 int analog_lib_handles (int signalling, int radio, int oprmode)
static void * analog_ss_thread (void *data)
static int analog_tone_to_dahditone (enum analog_tone tone)
static int analogsub_to_dahdisub (enum analog_sub analogsub)
 AST_DATA_STRUCTURE (dahdi_pvt, DATA_EXPORT_DAHDI_PVT)
static int attempt_transfer (struct dahdi_pvt *p)
static int available (struct dahdi_pvt **pvt, int is_specific_channel)
static int build_channels (struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
static int bump_gains (struct dahdi_pvt *p)
static int calc_energy (const unsigned char *buf, int len, format_t law)
static int canmatch_featurecode (const char *exten)
static int check_for_conference (struct dahdi_pvt *p)
static char * complete_span_4 (const char *line, const char *word, int pos, int state)
static char * complete_span_helper (const char *line, const char *word, int pos, int state, int rpos)
static int conf_add (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
static int conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
static struct ast_strcreate_channel_name (struct dahdi_pvt *i, int is_outgoing, char *address)
static int dahdi_accept_r2_call_exec (struct ast_channel *chan, const char *data)
static void dahdi_ami_channel_event (struct dahdi_pvt *p, struct ast_channel *chan)
static int dahdi_answer (struct ast_channel *ast)
static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause (int cause)
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 int dahdi_cc_callback (struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
 Callback made when dial failed to get a channel out of dahdi_request().
static struct dahdi_chan_conf dahdi_chan_conf_default (void)
static int dahdi_channels_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
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_devicestate (void *data)
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 int dahdi_dnd (struct dahdi_pvt *dahdichan, int flag)
 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_func_write (struct ast_channel *chan, const char *function, char *data, const char *value)
static int dahdi_get_event (int fd)
 Avoid the silly dahdi_getevent which ignores a bunch of events.
static void dahdi_handle_dtmf (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 void dahdi_iflist_extract (struct dahdi_pvt *pvt)
static void dahdi_iflist_insert (struct dahdi_pvt *pvt)
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_lock_sub_owner (struct dahdi_pvt *pvt, int sub_idx)
static struct ast_channeldahdi_new (struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
static int dahdi_new_pri_nobch_channel (struct sig_pri_span *pri)
static void dahdi_nobch_extract (struct sig_pri_span *pri, struct dahdi_pvt *pvt)
static void dahdi_nobch_insert (struct sig_pri_span *pri, struct dahdi_pvt *pvt)
static int dahdi_open (char *fn)
static void dahdi_pri_cc_agent_destructor (struct ast_cc_agent *agent)
static int dahdi_pri_cc_agent_init (struct ast_cc_agent *agent, struct ast_channel *chan)
static void dahdi_pri_error (struct pri *pri, char *s)
static void dahdi_pri_message (struct pri *pri, char *s)
static void dahdi_pri_update_span_devstate (struct sig_pri_span *pri)
static int dahdi_queryoption (struct ast_channel *chan, int option, void *data, int *datalen)
static void dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f)
static int16_t dahdi_r2_alaw_to_linear (uint8_t sample)
static int dahdi_r2_answer (struct dahdi_pvt *p)
static int dahdi_r2_cause_to_ast_cause (openr2_call_disconnect_cause_t cause)
static void dahdi_r2_destroy_links (void)
static void dahdi_r2_disconnect_call (struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
static openr2_calling_party_category_t dahdi_r2_get_channel_category (struct ast_channel *c)
static struct dahdi_mfcr2dahdi_r2_get_link (void)
static uint8_t dahdi_r2_linear_to_alaw (int sample)
static void dahdi_r2_on_ani_digit_received (openr2_chan_t *r2chan, char digit)
static void dahdi_r2_on_billing_pulse_received (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_accepted (openr2_chan_t *r2chan, openr2_call_mode_t mode)
static void dahdi_r2_on_call_answered (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_disconnect (openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
static void dahdi_r2_on_call_end (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_init (openr2_chan_t *r2chan)
static void dahdi_r2_on_call_offered (openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
static void dahdi_r2_on_call_read (openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
static void dahdi_r2_on_chan_log (openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
static void dahdi_r2_on_context_log (openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
static int dahdi_r2_on_dnis_digit_received (openr2_chan_t *r2chan, char digit)
static void dahdi_r2_on_hardware_alarm (openr2_chan_t *r2chan, int alarm)
static void dahdi_r2_on_line_blocked (openr2_chan_t *r2chan)
static void dahdi_r2_on_line_idle (openr2_chan_t *r2chan)
static void dahdi_r2_on_os_error (openr2_chan_t *r2chan, int errorcode)
static void dahdi_r2_on_protocol_error (openr2_chan_t *r2chan, openr2_protocol_error_t reason)
static int dahdi_r2_set_context (struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
static void dahdi_r2_write_log (openr2_log_level_t level, char *logmessage)
static struct ast_framedahdi_read (struct ast_channel *ast)
static struct ast_channeldahdi_request (const char *type, format_t format, const struct ast_channel *requestor, 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_callrerouting_facility_exec (struct ast_channel *chan, const char *data)
static int dahdi_send_keypad_facility_exec (struct ast_channel *chan, const char *digits)
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 int dahdi_sig_pri_lib_handles (int signaling)
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 int dahdi_status_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static void dahdi_train_ec (struct dahdi_pvt *p)
static void dahdi_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
static void dahdi_unlink_pri_pvt (struct dahdi_pvt *pvt)
static void dahdi_unlink_ss7_pvt (struct dahdi_pvt *pvt)
static int dahdi_version_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static int dahdi_wait_event (int fd)
 Avoid the silly dahdi_waitevent which ignores a bunch of events.
static int dahdi_wink (struct dahdi_pvt *p, int index)
static int dahdi_write (struct ast_channel *ast, struct ast_frame *frame)
static enum analog_event dahdievent_to_analogevent (int event)
static enum analog_sigtype dahdisig_to_analogsig (int sig)
static void deep_copy_dahdi_chan_conf (struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
static void destroy_all_channels (void)
static void destroy_channel (struct dahdi_pvt *cur, int now)
static void destroy_dahdi_pvt (struct dahdi_pvt *pvt)
static struct dahdi_pvtdetermine_starting_point (const char *data, struct dahdi_starting_point *param)
static int device2chan (const char *subdir, int channel, char *path, int pathlen)
static int digit_to_dtmfindex (char digit)
static void disable_dtmf_detect (struct dahdi_pvt *p)
static void * do_monitor (void *data)
static int drc_sample (int sample, float drc)
static struct dahdi_pvtduplicate_pseudo (struct dahdi_pvt *src)
static void enable_dtmf_detect (struct dahdi_pvt *p)
static const char * event2str (int event)
static void fill_rxgain (struct dahdi_gains *g, float gain, float drc, int law)
static void fill_txgain (struct dahdi_gains *g, float gain, float drc, int law)
static struct dahdi_pvtfind_channel (int channel)
static struct dahdi_pvtfind_channel_from_str (const char *channel)
static struct dahdi_pvtfind_next_iface_in_span (struct dahdi_pvt *cur)
static int get_alarms (struct dahdi_pvt *p)
static void handle_alarms (struct dahdi_pvt *p, int alms)
static void handle_clear_alarms (struct dahdi_pvt *p)
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_mfcr2_call_files (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_set_blocked (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_set_idle (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_show_variants (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mfcr2_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_service_disable_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_service_enable_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_service_generic (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
static char * handle_pri_set_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_show_channels (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_channels (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 is_group_or_channel_match (struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
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 void * mfcr2_monitor (void *data)
static struct dahdi_pvtmkintf (int channel, const struct dahdi_chan_conf *conf, 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 void my_all_subchannels_hungup (void *pvt)
static int my_allocate_sub (void *pvt, enum analog_sub analogsub)
static void my_ami_channel_event (void *pvt, struct ast_channel *chan)
static void my_answer_polarityswitch (void *pvt)
static int my_callwait (void *pvt)
static void my_cancel_cidspill (void *pvt)
static int my_check_confirmanswer (void *pvt)
static int my_check_for_conference (void *pvt)
static int my_check_waitingfordt (void *pvt)
static int my_complete_conference_update (void *pvt, int needconference)
static int my_conf_add (void *pvt, enum analog_sub sub)
static int my_conf_del (void *pvt, enum analog_sub sub)
static int my_confmute (void *pvt, int mute)
static int my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
static void my_deadlock_avoidance_private (void *pvt)
static void my_decrease_ss_count (void)
static int my_dial_digits (void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
static int my_distinctive_ring (struct ast_channel *chan, void *pvt, int idx, int *ringdata)
static int my_dsp_reset_and_flush_digits (void *pvt)
static int my_dsp_set_digitmode (void *pvt, enum analog_dsp_digitmode mode)
static int my_flash (void *pvt)
static void my_get_and_handle_alarms (void *pvt)
static int my_get_callerid (void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
static int my_get_event (void *pvt)
static const char * my_get_orig_dialstring (void *pvt)
static void * my_get_sigpvt_bridged_channel (struct ast_channel *chan)
static int my_get_sub_fd (void *pvt, enum analog_sub sub)
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
static void my_handle_dchan_exception (struct sig_pri_span *pri, int index)
static void my_handle_dtmf (void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
static void my_handle_link_exception (struct sig_ss7_linkset *linkset, int which)
static void my_handle_notify_message (struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
static void my_hangup_polarityswitch (void *pvt)
static int my_has_voicemail (void *pvt)
static int my_have_progressdetect (void *pvt)
static void my_increase_ss_count (void)
static int my_is_dialing (void *pvt, enum analog_sub sub)
static int my_is_off_hook (void *pvt)
static void my_lock_private (void *pvt)
static void my_module_ref (void)
static void my_module_unref (void)
static struct ast_channelmy_new_analog_ast_channel (void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
static struct ast_channelmy_new_pri_ast_channel (void *pvt, int state, enum sig_pri_law law, char *exten, const struct ast_channel *requestor)
static struct ast_channelmy_new_ss7_ast_channel (void *pvt, int state, enum sig_ss7_law law, char *exten, const struct ast_channel *requestor)
static int my_off_hook (void *pvt)
static int my_on_hook (void *pvt)
static int my_play_tone (void *pvt, enum analog_sub sub, enum analog_tone tone)
static void my_pri_fixup_chans (void *chan_old, void *chan_new)
static void my_pri_init_config (void *priv, struct sig_pri_span *pri)
static void my_pri_make_cc_dialstring (void *priv, char *buf, size_t buf_size)
static void my_pri_open_media (void *p)
static int my_pri_play_tone (void *pvt, enum sig_pri_tone tone)
static int my_ring (void *pvt)
static int my_send_callerid (void *pvt, int cwcid, struct ast_party_caller *caller)
static void my_set_alarm (void *pvt, int in_alarm)
static void my_set_cadence (void *pvt, int *cidrings, struct ast_channel *ast)
static void my_set_callerid (void *pvt, const struct ast_party_caller *caller)
static void my_set_callwaiting (void *pvt, int callwaiting_enable)
static void my_set_confirmanswer (void *pvt, int flag)
static void my_set_dialing (void *pvt, int is_dialing)
static void my_set_digital (void *pvt, int is_digital)
static void my_set_dnid (void *pvt, const char *dnid)
static int my_set_echocanceller (void *pvt, int enable)
static void my_set_inservice (void *pvt, int is_inservice)
static void my_set_inthreeway (void *pvt, enum analog_sub sub, int inthreeway)
static int my_set_linear_mode (void *pvt, enum analog_sub sub, int linear_mode)
static void my_set_locallyblocked (void *pvt, int is_blocked)
static void my_set_needringing (void *pvt, int value)
static void my_set_new_owner (void *pvt, struct ast_channel *new_owner)
static void my_set_polarity (void *pvt, int value)
static void my_set_pulsedial (void *pvt, int flag)
static void my_set_rdnis (void *pvt, const char *rdnis)
static void my_set_remotelyblocked (void *pvt, int is_blocked)
static void my_set_ringtimeout (void *pvt, int ringt)
static void my_set_waitingfordt (void *pvt, struct ast_channel *ast)
static int my_ss7_play_tone (void *pvt, enum sig_ss7_tone tone)
static void my_ss7_set_loopback (void *pvt, int enable)
static int my_start (void *pvt)
static int my_start_cid_detect (void *pvt, int cid_signalling)
static void my_start_polarityswitch (void *pvt)
static int my_stop_callwait (void *pvt)
static int my_stop_cid_detect (void *pvt)
static void my_swap_subchannels (void *pvt, enum analog_sub a, struct ast_channel *ast_a, enum analog_sub b, struct ast_channel *ast_b)
static int my_train_echocanceller (void *pvt)
static int my_unallocate_sub (void *pvt, enum analog_sub analogsub)
static void my_unlock_private (void *pvt)
static int my_wait_event (void *pvt)
static int my_wink (void *pvt, enum analog_sub sub)
static void notify_message (char *mailbox_full, int thereornot)
 Send MWI state change.
static int parse_buffers_policy (const char *parse, int *num_buffers, int *policy)
static unsigned int parse_pointcode (const char *pcstring)
static char * parse_spanchan (char *chanstr, char **subdir)
static int prepare_pri (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 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 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 revert_fax_buffers (struct dahdi_pvt *p, struct ast_channel *ast)
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, float rxgain, float txgain, float rxdrc, float txdrc, int law)
static int set_actual_rxgain (int fd, float gain, float drc, int law)
static int set_actual_txgain (int fd, float gain, float drc, int law)
static int setup_dahdi (int reload)
static int setup_dahdi_int (int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
static int sig_pri_tone_to_dahditone (enum sig_pri_tone tone)
static int sig_ss7_tone_to_dahditone (enum sig_ss7_tone tone)
static int sigtype_to_signalling (int sigtype)
static struct dahdi_ss7ss7_resolve_linkset (int linkset)
static void string_replace (char *str, int char1, int char2)
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)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = tdesc , .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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_smdi", }
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 const char *const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call"
static struct analog_callback dahdi_analog_callbacks
static struct ast_data_handler dahdi_channels_data_provider
static struct ast_cli_entry dahdi_cli []
static struct ast_data_entry dahdi_data_providers []
static struct ast_cli_entry dahdi_mfcr2_cli []
static struct sig_pri_callback dahdi_pri_callbacks
static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks
static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks
static const char dahdi_pri_cc_type [] = "DAHDI/PRI"
static struct ast_cli_entry dahdi_pri_cli []
static struct dahdi_parms_pseudo dahdi_pseudo_parms
static openr2_event_interface_t dahdi_r2_event_iface
static openr2_transcoder_interface_t dahdi_r2_transcode_iface
static char * dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility"
static char * dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility"
static struct sig_ss7_callback dahdi_ss7_callbacks
static struct ast_cli_entry dahdi_ss7_cli []
static struct ast_data_handler dahdi_status_data_provider
static struct ast_channel_tech dahdi_tech
static struct ast_data_handler dahdi_version_data_provider
static struct ast_jb_conf default_jbconf
static char defaultcic [64] = ""
static char defaultozz [64] = ""
static int distinctiveringaftercid = 0
static int dtmfcid_level = 256
static const char *const 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 = NULL
static struct dahdi_pvtiflist = NULL
static ast_mutex_t iflock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
 Protect the interface list (of dahdi_pvt's).
static const char *const 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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static int mwilevel = 512
static char mwimonitornotify [PATH_MAX] = ""
static int num_cadence = 4
static int num_restart_pending = 0
static int numbufs = 4
static int pridebugfd = -1
static ast_mutex_t pridebugfdlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static char pridebugfilename [1024] = ""
static struct dahdi_pri pris [NUM_SPANS]
static char progzone [10] = ""
static struct dahdi_mfcr2 ** r2links
static int r2links_count = 0
static int report_alarms = REPORT_CHANNEL_ALARMS
static ast_mutex_t restart_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base.
static 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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static const char *const subnames []
static const char tdesc []
static int usedistinctiveringdetection = 0
static int user_has_defined_cadences = 0


Detailed Description

DAHDI for Pseudo TDM.

Author:
Mark Spencer <markster@digium.com>
Connects to the DAHDI telephony library as well as libpri. Libpri is optional and needed only if you are going to use ISDN connections.

You need to install libraries before you attempt to compile and install the DAHDI channel.

See also
Todo:
Deprecate the "musiconhold" configuration option post 1.4

Definition in file chan_dahdi.c.


Define Documentation

#define ASCII_BYTES_PER_CHAR   80

Referenced by dahdi_sendtext().

#define AST_LAW (  )     (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)

Definition at line 314 of file chan_dahdi.c.

Referenced by analog_ss_thread(), dahdi_callwait(), dahdi_sendtext(), mwi_send_init(), mwi_thread(), my_callwait(), my_get_callerid(), my_send_callerid(), and send_cwcidspill().

#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)

Definition at line 381 of file chan_dahdi.c.

Referenced by dahdi_handle_dtmf(), and my_handle_dtmf().

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 380 of file chan_dahdi.c.

Referenced by dahdi_new().

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 379 of file chan_dahdi.c.

Referenced by dahdi_new().

#define CALLPROGRESS_PROGRESS   1

Definition at line 378 of file chan_dahdi.c.

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

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

10,000 ms

Definition at line 516 of file chan_dahdi.c.

Referenced by dahdi_callwait(), and my_callwait().

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

300 ms

Definition at line 515 of file chan_dahdi.c.

#define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE)

100 ms

Definition at line 517 of file chan_dahdi.c.

Referenced by send_callerid().

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

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

Referenced by dahdi_handle_event(), dahdi_new(), my_have_progressdetect(), and my_set_waitingfordt().

#define CHAN_PSEUDO   -2

Definition at line 376 of file chan_dahdi.c.

Referenced by build_channels(), create_channel_name(), dahdi_ami_channel_event(), dahdi_new(), dahdi_new_pri_nobch_channel(), dahdi_request(), determine_starting_point(), enable_dtmf_detect(), my_dsp_set_digitmode(), and my_set_polarity().

#define CHAN_TAG   "Chan "

Referenced by dahdi_r2_on_chan_log().

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

500 ms

Definition at line 518 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 652 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 653 of file chan_dahdi.c.

#define CONTEXT_TAG   "Context - "

Referenced by dahdi_r2_on_context_log().

#define dahdi_get_index ( ast,
p,
nullok   )     _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)

Definition at line 3684 of file chan_dahdi.c.

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_answer(), dahdi_bridge(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), and dahdi_write().

#define DATA_EXPORT_DAHDI_PVT ( MEMBER   ) 

Definition at line 1244 of file chan_dahdi.c.

#define DEFAULT_CIDRINGS   1

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

Definition at line 312 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

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

8,000 ms

Definition at line 520 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 FORMAT   "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"

#define FORMAT   "%4s %40s\n"

Referenced by __iax2_show_peers(), _sip_show_peers(), alias_show(), dahdi_show_status(), dundi_show_mappings(), dundi_show_peers(), dundi_show_precache(), dundi_show_requests(), dundi_show_trans(), gtalk_show_channels(), handle_cli_core_show_channeltypes(), handle_cli_core_show_file_formats(), handle_cli_iax2_show_channels(), handle_cli_iax2_show_registry(), handle_cli_iax2_show_users(), handle_cli_keys_show(), handle_core_show_image_formats(), handle_manager_show_settings(), handle_mfcr2_show_channels(), handle_mfcr2_show_variants(), handle_show_calendar(), handle_show_calendars(), handle_show_routes(), handle_show_version_files(), jingle_show_channels(), show_channels_cb(), show_chanstats_cb(), sip_show_domains(), sip_show_inuse(), sip_show_mwi(), sip_show_registry(), sip_show_tcp(), and sip_show_users().

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

Referenced by __iax2_show_peers(), _sip_show_peers(), dahdi_show_channels(), dahdi_show_status(), dundi_show_mappings(), dundi_show_peers(), dundi_show_precache(), dundi_show_requests(), dundi_show_trans(), handle_cli_core_show_file_formats(), handle_cli_iax2_show_channels(), handle_cli_iax2_show_registry(), handle_cli_iax2_show_users(), handle_core_show_image_formats(), handle_manager_show_settings(), handle_show_calendar(), sip_show_channels(), sip_show_channelstats(), sip_show_inuse(), sip_show_registry(), and sip_show_tcp().

#define GET_CHANNEL (  )     ((p)->channel)

Definition at line 1537 of file chan_dahdi.c.

Referenced by my_complete_conference_update().

#define HANGUP   1

Definition at line 15749 of file chan_dahdi.c.

Referenced by action_transferhangup(), and dahdi_fake_event().

#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)

Referenced by build_alerting(), build_connect(), build_connect_acknowledge(), build_disconnect(), build_facility(), build_hold(), build_hold_acknowledge(), build_hold_reject(), build_proceeding(), build_progress(), build_release(), build_release_complete(), build_restart(), build_resume(), build_resume_acknowledge(), build_resume_reject(), build_retrieve(), build_retrieve_acknowledge(), build_retrieve_reject(), build_setup(), build_setup_acknowledge(), build_suspend(), build_suspend_acknowledge(), build_suspend_reject(), build_user_information(), dahdi_sendtext(), parse_alerting(), parse_connect(), parse_disconnect(), parse_facility(), parse_proceeding(), parse_progress(), parse_release(), parse_release_complete(), parse_restart(), parse_setup(), and parse_setup_acknowledge().

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

Referenced by __analog_ss_thread(), analog_ss_thread(), and dahdi_indicate().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 512 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

#define MAX_SLAVES   4

Definition at line 655 of file chan_dahdi.c.

Referenced by isslavenative(), and my_complete_conference_update().

#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

Definition at line 519 of file chan_dahdi.c.

Referenced by __analog_handle_event(), and 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 318 of file chan_dahdi.c.

Referenced by analog_ss_thread(), and dahdi_new().

#define NUM_CADENCE_MAX   25

Definition at line 383 of file chan_dahdi.c.

#define NUM_SPANS   32

Definition at line 373 of file chan_dahdi.c.

Referenced by destroy_all_channels(), pri_create_trunkgroup(), pri_resolve_span(), and ss7_resolve_linkset().

#define POLARITY_IDLE   0

Definition at line 612 of file chan_dahdi.c.

Referenced by __analog_handle_event(), __analog_ss_thread(), analog_hangup(), dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().

#define POLARITY_REV   1

Definition at line 613 of file chan_dahdi.c.

Referenced by __analog_handle_event(), __analog_ss_thread(), analog_handle_init_event(), dahdi_handle_event(), and handle_init_event().

#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)

process_dahdi() - ignore keyword 'channel' and similar

Definition at line 16825 of file chan_dahdi.c.

Referenced by process_dahdi().

#define PROC_DAHDI_OPT_NOWARN   (1 << 1)

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

Definition at line 16827 of file chan_dahdi.c.

Referenced by setup_dahdi_int().

#define R2_LINK_CAPACITY   10

Definition at line 12033 of file chan_dahdi.c.

Referenced by dahdi_r2_get_link().

#define READ_SIZE   160

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

Definition at line 510 of file chan_dahdi.c.

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

#define REPORT_CHANNEL_ALARMS   1

Definition at line 433 of file chan_dahdi.c.

Referenced by handle_alarms(), and handle_clear_alarms().

#define REPORT_SPAN_ALARMS   2

Definition at line 434 of file chan_dahdi.c.

Referenced by handle_alarms(), and handle_clear_alarms().

#define sig2str   dahdi_sig2str

Definition at line 4610 of file chan_dahdi.c.

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

#define SIG_BRI   (0x2000000 | DAHDI_SIG_CLEAR)

Definition at line 359 of file chan_dahdi.c.

Referenced by dahdi_sig2str(), and sig_pri_start_pri().

#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)

Definition at line 360 of file chan_dahdi.c.

Referenced by dahdi_sig2str(), pri_dchannel(), sig_pri_cc_generic_check(), and sig_pri_start_pri().

#define SIG_E911   (0x1000000 | DAHDI_SIG_EM)

Definition at line 348 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_EM   DAHDI_SIG_EM

Definition at line 343 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_EM_E1   DAHDI_SIG_EM_E1

Definition at line 368 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)

Definition at line 344 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)

Definition at line 347 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)

Definition at line 345 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)

Definition at line 346 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)

Definition at line 349 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)

Definition at line 350 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)

Definition at line 351 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FXOGS   DAHDI_SIG_FXOGS

Definition at line 356 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FXOKS   DAHDI_SIG_FXOKS

Definition at line 357 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FXOLS   DAHDI_SIG_FXOLS

Definition at line 355 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_FXSGS   DAHDI_SIG_FXSGS

Definition at line 353 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), dahdisig_to_analogsig(), do_monitor(), handle_init_event(), and my_is_off_hook().

#define SIG_FXSKS   DAHDI_SIG_FXSKS

Definition at line 354 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), dahdisig_to_analogsig(), do_monitor(), handle_init_event(), and my_is_off_hook().

#define SIG_FXSLS   DAHDI_SIG_FXSLS

Definition at line 352 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), dahdisig_to_analogsig(), do_monitor(), and handle_init_event().

#define SIG_MFCR2   DAHDI_SIG_CAS

Definition at line 362 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_func_read(), dahdi_handle_event(), dahdi_hangup(), dahdi_sig2str(), do_monitor(), handle_mfcr2_call_files(), handle_mfcr2_set_blocked(), handle_mfcr2_set_debug(), handle_mfcr2_set_idle(), and handle_mfcr2_show_channels().

#define SIG_MFCR2_MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 84 of file chan_dahdi.c.

#define SIG_PRI   DAHDI_SIG_CLEAR

Definition at line 358 of file chan_dahdi.c.

Referenced by dahdi_indicate(), and dahdi_sig2str().

#define SIG_PRI_LIB_HANDLE_CASES

Value:

SIG_PRI:                \
   case SIG_BRI:              \
   case SIG_BRI_PTMP

Definition at line 1539 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_bridge(), dahdi_confmute(), dahdi_digit_begin(), dahdi_enable_ec(), dahdi_func_read(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_send_callrerouting_facility_exec(), dahdi_sig_pri_lib_handles(), destroy_dahdi_pvt(), handle_init_event(), and my_new_pri_ast_channel().

#define SIG_SF   DAHDI_SIG_SF

Definition at line 363 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)

Definition at line 367 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)

Definition at line 365 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)

Definition at line 366 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)

Definition at line 364 of file chan_dahdi.c.

Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().

#define SIG_SS7   (0x1000000 | DAHDI_SIG_CLEAR)

Definition at line 361 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_enable_ec(), dahdi_func_read(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_sig2str(), destroy_dahdi_pvt(), and handle_init_event().

#define SMDI_MD_WAIT_TIMEOUT   1500

Definition at line 275 of file chan_dahdi.c.

Referenced by analog_ss_thread().

#define SUB_CALLWAIT   1

Call-Waiting call on hold

Definition at line 608 of file chan_dahdi.c.

Referenced by _dahdi_get_index(), analog_ss_thread(), analogsub_to_dahdisub(), dahdi_bridge(), dahdi_handle_event(), dahdi_hangup(), dahdi_read(), dahdi_request(), and dahdi_show_channel().

#define SUB_REAL   0

Active call

Definition at line 607 of file chan_dahdi.c.

Referenced by __dahdi_exception(), _dahdi_get_index(), analog_ss_thread(), analogsub_to_dahdisub(), attempt_transfer(), build_device(), bump_gains(), check_for_conference(), close_call(), close_client(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_confmute(), dahdi_destroy_channel_bynum(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_func_write(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_r2_on_call_accepted(), dahdi_r2_on_call_answered(), dahdi_r2_on_call_disconnect(), dahdi_r2_on_call_offered(), dahdi_read(), dahdi_request(), dahdi_ring_phone(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_setoption(), dahdi_show_channel(), dahdi_train_ec(), dahdi_unlink(), destroy_dahdi_pvt(), disable_dtmf_detect(), do_monitor(), duplicate_pseudo(), enable_dtmf_detect(), find_subchannel_by_name(), get_alarms(), handle_init_event(), HandleCallIncoming(), HandleCallOutgoing(), key_call(), key_dial_page(), mfcr2_monitor(), mwi_send_init(), mwi_send_process_buffer(), mwi_send_process_event(), mwi_thread(), my_all_subchannels_hungup(), my_complete_conference_update(), my_flash(), my_get_callerid(), my_get_event(), my_is_off_hook(), my_new_pri_ast_channel(), my_new_ss7_ast_channel(), my_off_hook(), my_pri_fixup_chans(), my_pri_open_media(), my_pri_play_tone(), my_set_cadence(), my_set_needringing(), my_set_polarity(), my_ss7_play_tone(), my_ss7_set_loopback(), my_start(), my_start_cid_detect(), my_stop_cid_detect(), my_wait_event(), my_wink(), process_request(), rcv_mac_addr(), reset_conf(), restore_conference(), restore_gains(), revert_fax_buffers(), save_conference(), send_callerid(), TransferCallStep1(), unistim_do_senddigit(), unistim_hangup(), and unistim_senddigit_end().

#define SUB_THREEWAY   2

Three-way call

Definition at line 609 of file chan_dahdi.c.

Referenced by _dahdi_get_index(), analog_ss_thread(), analogsub_to_dahdisub(), attempt_transfer(), close_call(), dahdi_bridge(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), HandleCallOutgoing(), TransferCallStep1(), unistim_answer(), and unistim_hangup().

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

Definition at line 15748 of file chan_dahdi.c.

Referenced by action_transfer(), and dahdi_fake_event().


Enumeration Type Documentation

enum DAHDI_IFLIST

Specify the lists dahdi_pvt can be put in.

Enumerator:
DAHDI_IFLIST_NONE  The dahdi_pvt is not in any list.
DAHDI_IFLIST_MAIN  The dahdi_pvt is in the main interface list
DAHDI_IFLIST_NO_B_CHAN  The dahdi_pvt is in a no B channel interface list

Definition at line 676 of file chan_dahdi.c.

00676                   {
00677    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00678    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00679 #if defined(HAVE_PRI)
00680    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00681 #endif   /* defined(HAVE_PRI) */
00682 };

enum mwisend_states

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

00660              {
00661    MWI_SEND_NULL = 0,
00662    MWI_SEND_SA,
00663    MWI_SEND_SA_WAIT,
00664    MWI_SEND_PAUSE,
00665    MWI_SEND_SPILL,
00666    MWI_SEND_CLEANUP,
00667    MWI_SEND_DONE,
00668 } mwisend_states;


Function Documentation

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

Definition at line 8672 of file chan_dahdi.c.

References ast_bridged_channel(), AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_set_hangupsource(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_tvnow(), ast_verb, dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index, dahdi_handle_event(), dahdi_ring_phone(), dahdi_set_hook(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, event2str(), dahdi_subchannel::f, f, dahdi_pvt::fake_event, ast_channel::fds, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::mallocd, ast_channel::name, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, ast_frame::ptr, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().

Referenced by dahdi_exception(), and dahdi_read().

08673 {
08674    int res;
08675    int idx;
08676    struct ast_frame *f;
08677    int usedindex = -1;
08678    struct dahdi_pvt *p = ast->tech_pvt;
08679 
08680    idx = dahdi_get_index(ast, p, 1);
08681 
08682    p->subs[idx].f.frametype = AST_FRAME_NULL;
08683    p->subs[idx].f.datalen = 0;
08684    p->subs[idx].f.samples = 0;
08685    p->subs[idx].f.mallocd = 0;
08686    p->subs[idx].f.offset = 0;
08687    p->subs[idx].f.subclass.integer = 0;
08688    p->subs[idx].f.delivery = ast_tv(0,0);
08689    p->subs[idx].f.src = "dahdi_exception";
08690    p->subs[idx].f.data.ptr = NULL;
08691 
08692 
08693    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08694       /* If nobody owns us, absorb the event appropriately, otherwise
08695          we loop indefinitely.  This occurs when, during call waiting, the
08696          other end hangs up our channel so that it no longer exists, but we
08697          have neither FLASH'd nor ONHOOK'd to signify our desire to
08698          change to the other channel. */
08699       if (p->fake_event) {
08700          res = p->fake_event;
08701          p->fake_event = 0;
08702       } else
08703          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08704       /* Switch to real if there is one and this isn't something really silly... */
08705       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08706          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08707          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08708          p->owner = p->subs[SUB_REAL].owner;
08709          if (p->owner && ast_bridged_channel(p->owner))
08710             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08711          p->subs[SUB_REAL].needunhold = 1;
08712       }
08713       switch (res) {
08714       case DAHDI_EVENT_ONHOOK:
08715          dahdi_disable_ec(p);
08716          if (p->owner) {
08717             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08718             dahdi_ring_phone(p);
08719             p->callwaitingrepeat = 0;
08720             p->cidcwexpire = 0;
08721             p->cid_suppress_expire = 0;
08722          } else
08723             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08724          update_conf(p);
08725          break;
08726       case DAHDI_EVENT_RINGOFFHOOK:
08727          dahdi_enable_ec(p);
08728          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08729          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08730             p->subs[SUB_REAL].needanswer = 1;
08731             p->dialing = 0;
08732          }
08733          break;
08734       case DAHDI_EVENT_HOOKCOMPLETE:
08735       case DAHDI_EVENT_RINGERON:
08736       case DAHDI_EVENT_RINGEROFF:
08737          /* Do nothing */
08738          break;
08739       case DAHDI_EVENT_WINKFLASH:
08740          p->flashtime = ast_tvnow();
08741          if (p->owner) {
08742             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08743             if (p->owner->_state != AST_STATE_UP) {
08744                /* Answer if necessary */
08745                usedindex = dahdi_get_index(p->owner, p, 0);
08746                if (usedindex > -1) {
08747                   p->subs[usedindex].needanswer = 1;
08748                }
08749                ast_setstate(p->owner, AST_STATE_UP);
08750             }
08751             p->callwaitingrepeat = 0;
08752             p->cidcwexpire = 0;
08753             p->cid_suppress_expire = 0;
08754             if (ast_bridged_channel(p->owner))
08755                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08756             p->subs[SUB_REAL].needunhold = 1;
08757          } else
08758             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08759          update_conf(p);
08760          break;
08761       default:
08762          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08763       }
08764       f = &p->subs[idx].f;
08765       return f;
08766    }
08767    if (!(p->radio || (p->oprmode < 0)))
08768       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08769    /* If it's not us, return NULL immediately */
08770    if (ast != p->owner) {
08771       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08772       f = &p->subs[idx].f;
08773       return f;
08774    }
08775    f = dahdi_handle_event(ast);
08776 
08777    /* tell the cdr this zap device hung up */
08778    if (f == NULL) {
08779       ast_set_hangupsource(ast, ast->name, 0);
08780    }
08781 
08782    return f;
08783 }

static void __reg_module ( void   )  [static]

Definition at line 18633 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

Definition at line 16571 of file chan_dahdi.c.

References ARRAY_LEN, ast_cc_agent_unregister(), ast_cc_monitor_unregister(), ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy, ast_data_unregister, ast_manager_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), dahdi_cli, dahdi_close_pri_fd(), dahdi_close_ss7_fd(), dahdi_mfcr2_cli, dahdi_pri_cc_agent_callbacks, dahdi_pri_cc_monitor_callbacks, dahdi_pri_cli, dahdi_r2_destroy_links(), dahdi_ss7_cli, dahdi_tech, destroy_all_channels(), iflist, sig_ss7_linkset::master, sig_pri_span::master, monitor_thread, monlock, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::pri, sig_pri_stop_pri(), sig_pri_unload(), dahdi_pvt::ss7, and ss_thread_complete.

Referenced by load_module(), and unload_module().

16572 {
16573    struct dahdi_pvt *p;
16574 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16575    int i, j;
16576 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16577 
16578 #ifdef HAVE_PRI
16579    for (i = 0; i < NUM_SPANS; i++) {
16580       if (pris[i].pri.master != AST_PTHREADT_NULL)
16581          pthread_cancel(pris[i].pri.master);
16582    }
16583    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16584    ast_unregister_application(dahdi_send_keypad_facility_app);
16585 #ifdef HAVE_PRI_PROG_W_CAUSE
16586    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16587 #endif
16588 #endif
16589 #if defined(HAVE_SS7)
16590    for (i = 0; i < NUM_SPANS; i++) {
16591       if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16592          pthread_cancel(linksets[i].ss7.master);
16593       }
16594    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16595 #endif   /* defined(HAVE_SS7) */
16596 #if defined(HAVE_OPENR2)
16597    dahdi_r2_destroy_links();
16598    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16599    ast_unregister_application(dahdi_accept_r2_call_app);
16600 #endif
16601 
16602    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16603    ast_manager_unregister("DAHDIDialOffhook");
16604    ast_manager_unregister("DAHDIHangup");
16605    ast_manager_unregister("DAHDITransfer");
16606    ast_manager_unregister("DAHDIDNDoff");
16607    ast_manager_unregister("DAHDIDNDon");
16608    ast_manager_unregister("DAHDIShowChannels");
16609    ast_manager_unregister("DAHDIRestart");
16610    ast_data_unregister(NULL);
16611    ast_channel_unregister(&dahdi_tech);
16612 
16613    /* Hangup all interfaces if they have an owner */
16614    ast_mutex_lock(&iflock);
16615    for (p = iflist; p; p = p->next) {
16616       if (p->owner)
16617          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16618    }
16619    ast_mutex_unlock(&iflock);
16620 
16621    ast_mutex_lock(&monlock);
16622    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16623       pthread_cancel(monitor_thread);
16624       pthread_kill(monitor_thread, SIGURG);
16625       pthread_join(monitor_thread, NULL);
16626    }
16627    monitor_thread = AST_PTHREADT_STOP;
16628    ast_mutex_unlock(&monlock);
16629 
16630    destroy_all_channels();
16631 
16632 #if defined(HAVE_PRI)
16633    for (i = 0; i < NUM_SPANS; i++) {
16634       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16635          pthread_join(pris[i].pri.master, NULL);
16636       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16637          dahdi_close_pri_fd(&(pris[i]), j);
16638       }
16639       sig_pri_stop_pri(&pris[i].pri);
16640    }
16641 #if defined(HAVE_PRI_CCSS)
16642    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16643    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16644 #endif   /* defined(HAVE_PRI_CCSS) */
16645    sig_pri_unload();
16646 #endif
16647 
16648 #if defined(HAVE_SS7)
16649    for (i = 0; i < NUM_SPANS; i++) {
16650       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16651          pthread_join(linksets[i].ss7.master, NULL);
16652       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16653          dahdi_close_ss7_fd(&(linksets[i]), j);
16654       }
16655    }
16656 #endif   /* defined(HAVE_SS7) */
16657    ast_cond_destroy(&ss_thread_complete);
16658    return 0;
16659 }

static void __unreg_module ( void   )  [static]

Definition at line 18633 of file chan_dahdi.c.

static int _dahdi_get_index ( struct ast_channel ast,
struct dahdi_pvt p,
int  nullok,
const char *  fname,
unsigned long  line 
) [static]

Definition at line 3685 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, LOG_WARNING, ast_channel::name, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.

03686 {
03687    int res;
03688    if (p->subs[SUB_REAL].owner == ast)
03689       res = 0;
03690    else if (p->subs[SUB_CALLWAIT].owner == ast)
03691       res = 1;
03692    else if (p->subs[SUB_THREEWAY].owner == ast)
03693       res = 2;
03694    else {
03695       res = -1;
03696       if (!nullok)
03697          ast_log(LOG_WARNING,
03698             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03699             ast ? ast->name : "", p->channel, fname, line);
03700    }
03701    return res;
03702 }

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

Definition at line 15886 of file chan_dahdi.c.

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

Referenced by load_module().

15887 {
15888    struct dahdi_pvt *p;
15889    const char *channel = astman_get_header(m, "DAHDIChannel");
15890    const char *number = astman_get_header(m, "Number");
15891    int i;
15892 
15893    if (ast_strlen_zero(channel)) {
15894       astman_send_error(s, m, "No channel specified");
15895       return 0;
15896    }
15897    if (ast_strlen_zero(number)) {
15898       astman_send_error(s, m, "No number specified");
15899       return 0;
15900    }
15901    p = find_channel_from_str(channel);
15902    if (!p) {
15903       astman_send_error(s, m, "No such channel");
15904       return 0;
15905    }
15906    if (!p->owner) {
15907       astman_send_error(s, m, "Channel does not have it's owner");
15908       return 0;
15909    }
15910    for (i = 0; i < strlen(number); i++) {
15911       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
15912       dahdi_queue_frame(p, &f);
15913    }
15914    astman_send_ack(s, m, "DAHDIDialOffhook");
15915    return 0;
15916 }

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

Definition at line 15821 of file chan_dahdi.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_dnd(), and find_channel_from_str().

Referenced by load_module().

15822 {
15823    struct dahdi_pvt *p;
15824    const char *channel = astman_get_header(m, "DAHDIChannel");
15825 
15826    if (ast_strlen_zero(channel)) {
15827       astman_send_error(s, m, "No channel specified");
15828       return 0;
15829    }
15830    p = find_channel_from_str(channel);
15831    if (!p) {
15832       astman_send_error(s, m, "No such channel");
15833       return 0;
15834    }
15835    dahdi_dnd(p, 0);
15836    astman_send_ack(s, m, "DND Disabled");
15837    return 0;
15838 }

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

Definition at line 15802 of file chan_dahdi.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_dnd(), and find_channel_from_str().

Referenced by load_module().

15803 {
15804    struct dahdi_pvt *p;
15805    const char *channel = astman_get_header(m, "DAHDIChannel");
15806 
15807    if (ast_strlen_zero(channel)) {
15808       astman_send_error(s, m, "No channel specified");
15809       return 0;
15810    }
15811    p = find_channel_from_str(channel);
15812    if (!p) {
15813       astman_send_error(s, m, "No such channel");
15814       return 0;
15815    }
15816    dahdi_dnd(p, 1);
15817    astman_send_ack(s, m, "DND Enabled");
15818    return 0;
15819 }

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

Definition at line 15086 of file chan_dahdi.c.

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

Referenced by load_module().

15087 {
15088    if (dahdi_restart() != 0) {
15089       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15090       return 1;
15091    }
15092    astman_send_ack(s, m, "DAHDIRestart: Success");
15093    return 0;
15094 }

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

Definition at line 15918 of file chan_dahdi.c.

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

Referenced by load_module().

15919 {
15920    struct dahdi_pvt *tmp = NULL;
15921    const char *id = astman_get_header(m, "ActionID");
15922    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15923    char idText[256] = "";
15924    int channels = 0;
15925    int dahdichanquery;
15926 
15927    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
15928       /* Not numeric string. */
15929       dahdichanquery = -1;
15930    }
15931 
15932    astman_send_ack(s, m, "DAHDI channel status will follow");
15933    if (!ast_strlen_zero(id))
15934       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15935 
15936    ast_mutex_lock(&iflock);
15937 
15938    for (tmp = iflist; tmp; tmp = tmp->next) {
15939       if (tmp->channel > 0) {
15940          int alm;
15941 
15942          /* If a specific channel is queried for, only deliver status for that channel */
15943          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15944             continue;
15945 
15946          alm = get_alarms(tmp);
15947          channels++;
15948          if (tmp->owner) {
15949             /* Add data if we have a current call */
15950             astman_append(s,
15951                "Event: DAHDIShowChannels\r\n"
15952                "DAHDIChannel: %d\r\n"
15953                "Channel: %s\r\n"
15954                "Uniqueid: %s\r\n"
15955                "AccountCode: %s\r\n"
15956                "Signalling: %s\r\n"
15957                "SignallingCode: %d\r\n"
15958                "Context: %s\r\n"
15959                "DND: %s\r\n"
15960                "Alarm: %s\r\n"
15961                "%s"
15962                "\r\n",
15963                tmp->channel,
15964                tmp->owner->name,
15965                tmp->owner->uniqueid,
15966                tmp->owner->accountcode,
15967                sig2str(tmp->sig),
15968                tmp->sig,
15969                tmp->context,
15970                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15971                alarm2str(alm), idText);
15972          } else {
15973             astman_append(s,
15974                "Event: DAHDIShowChannels\r\n"
15975                "DAHDIChannel: %d\r\n"
15976                "Signalling: %s\r\n"
15977                "SignallingCode: %d\r\n"
15978                "Context: %s\r\n"
15979                "DND: %s\r\n"
15980                "Alarm: %s\r\n"
15981                "%s"
15982                "\r\n",
15983                tmp->channel, sig2str(tmp->sig), tmp->sig,
15984                tmp->context,
15985                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15986                alarm2str(alm), idText);
15987          }
15988       }
15989    }
15990 
15991    ast_mutex_unlock(&iflock);
15992 
15993    astman_append(s,
15994       "Event: DAHDIShowChannelsComplete\r\n"
15995       "%s"
15996       "Items: %d\r\n"
15997       "\r\n",
15998       idText,
15999       channels);
16000    return 0;
16001 }

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

Definition at line 15840 of file chan_dahdi.c.

References analog_lib_handles(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel_from_str(), dahdi_pvt::sig, and TRANSFER.

Referenced by load_module().

15841 {
15842    struct dahdi_pvt *p;
15843    const char *channel = astman_get_header(m, "DAHDIChannel");
15844 
15845    if (ast_strlen_zero(channel)) {
15846       astman_send_error(s, m, "No channel specified");
15847       return 0;
15848    }
15849    p = find_channel_from_str(channel);
15850    if (!p) {
15851       astman_send_error(s, m, "No such channel");
15852       return 0;
15853    }
15854    if (!analog_lib_handles(p->sig, 0, 0)) {
15855       astman_send_error(s, m, "Channel signaling is not analog");
15856       return 0;
15857    }
15858    dahdi_fake_event(p,TRANSFER);
15859    astman_send_ack(s, m, "DAHDITransfer");
15860    return 0;
15861 }

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

Definition at line 15863 of file chan_dahdi.c.

References analog_lib_handles(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel_from_str(), HANGUP, and dahdi_pvt::sig.

Referenced by load_module().

15864 {
15865    struct dahdi_pvt *p;
15866    const char *channel = astman_get_header(m, "DAHDIChannel");
15867 
15868    if (ast_strlen_zero(channel)) {
15869       astman_send_error(s, m, "No channel specified");
15870       return 0;
15871    }
15872    p = find_channel_from_str(channel);
15873    if (!p) {
15874       astman_send_error(s, m, "No such channel");
15875       return 0;
15876    }
15877    if (!analog_lib_handles(p->sig, 0, 0)) {
15878       astman_send_error(s, m, "Channel signaling is not analog");
15879       return 0;
15880    }
15881    dahdi_fake_event(p,HANGUP);
15882    astman_send_ack(s, m, "DAHDIHangup");
15883    return 0;
15884 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 4527 of file chan_dahdi.c.

References alarm, alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

04528 {
04529    int x;
04530    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04531       if (alarms[x].alarm & alm)
04532          return alarms[x].name;
04533    }
04534    return alm ? "Unknown Alarm" : "No Alarm";
04535 }

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

Definition at line 4331 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, subnames, and dahdi_pvt::subs.

Referenced by analog_ss_thread(), build_device(), dahdi_handle_event(), HandleCallOutgoing(), my_allocate_sub(), and rcv_mac_addr().

04332 {
04333    struct dahdi_bufferinfo bi;
04334    int res;
04335    if (p->subs[x].dfd >= 0) {
04336       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04337       return -1;
04338    }
04339 
04340    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04341    if (p->subs[x].dfd <= -1) {
04342       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04343       return -1;
04344    }
04345 
04346    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04347    if (!res) {
04348       bi.txbufpolicy = p->buf_policy;
04349       bi.rxbufpolicy = p->buf_policy;
04350       bi.numbufs = p->buf_no;
04351       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04352       if (res < 0) {
04353          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04354       }
04355    } else
04356       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04357 
04358    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04359       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04360       dahdi_close_sub(p, x);
04361       p->subs[x].dfd = -1;
04362       return -1;
04363    }
04364    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04365    return 0;
04366 }

static int analog_lib_handles ( int  signalling,
int  radio,
int  oprmode 
) [static]

Definition at line 4612 of file chan_dahdi.c.

References 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_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.

Referenced by action_transfer(), action_transferhangup(), available(), dahdi_answer(), dahdi_call(), dahdi_dnd(), dahdi_exception(), dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_request(), destroy_dahdi_pvt(), do_monitor(), and mwi_thread().

04613 {
04614    switch (signalling) {
04615    case SIG_FXOLS:
04616    case SIG_FXOGS:
04617    case SIG_FXOKS:
04618    case SIG_FXSLS:
04619    case SIG_FXSGS:
04620    case SIG_FXSKS:
04621    case SIG_EMWINK:
04622    case SIG_EM:
04623    case SIG_EM_E1:
04624    case SIG_FEATD:
04625    case SIG_FEATDMF:
04626    case SIG_E911:
04627    case SIG_FGC_CAMA:
04628    case SIG_FGC_CAMAMF:
04629    case SIG_FEATB:
04630    case SIG_SFWINK:
04631    case SIG_SF:
04632    case SIG_SF_FEATD:
04633    case SIG_SF_FEATDMF:
04634    case SIG_FEATDMF_TA:
04635    case SIG_SF_FEATB:
04636       break;
04637    default:
04638       /* The rest of the function should cover the remainder of signalling types */
04639       return 0;
04640    }
04641 
04642    if (radio)
04643       return 0;
04644 
04645    if (oprmode)
04646       return 0;
04647 
04648    return 1;
04649 }

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

Definition at line 9801 of file chan_dahdi.c.

References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), ast_clear_flag, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_dsp_digitreset(), ast_dsp_free(), ast_dsp_set_digitmode(), ast_exists_extension(), AST_FLAG_END_DTMF_ONLY, AST_FRAME_DTMF, ast_frfree, ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log(), ast_masq_park_call_exten(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_parking_ext_valid(), ast_party_name_free(), ast_party_name_init(), ast_party_number_free(), ast_party_number_init(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_queue_control(), ast_read(), ast_safe_sleep(), ast_set_callerid(), ast_set_flag, ast_setstate(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_streamfile(), ast_strlen_zero(), ast_verb, ast_waitfor(), ast_waitfordigit(), ast_waitstream(), bump_gains(), dahdi_pvt::call_forward, ast_channel::caller, 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, canmatch_featurecode(), dahdi_pvt::canpark, dahdi_pvt::channel, dahdi_pvt::cid_name, 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_DTMF_NOALERT, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, dahdi_pvt::cs, dahdi_dnd(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index, dahdi_set_hook(), dahdi_setlinear(), dahdi_tech, dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), ast_channel::exten, exten, f, firstdigittimeout, ast_smdi_md_message::fwd_st, gendigittimeout, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, ast_party_caller::id, dahdi_pvt::immediate, dahdi_pvt::inalarm, ISTRUNK, ast_channel::language, len(), dahdi_subchannel::linear, LOG_NOTICE, matchdigittimeout, my_getsigstr(), ast_party_id::name, ast_channel::name, name, NEED_MFDETECT, ast_party_id::number, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_COR, S_OR, dahdi_pvt::sig, 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_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, ss_thread_count, ss_thread_lock, ast_party_number::str, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), dahdi_pvt::use_callerid, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, and ast_party_number::valid.

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

09802 {
09803    struct ast_channel *chan = data;
09804    struct dahdi_pvt *p = chan->tech_pvt;
09805    char exten[AST_MAX_EXTENSION] = "";
09806    char exten2[AST_MAX_EXTENSION] = "";
09807    unsigned char buf[256];
09808    char dtmfcid[300];
09809    char dtmfbuf[300];
09810    struct callerid_state *cs = NULL;
09811    char *name = NULL, *number = NULL;
09812    int distMatches;
09813    int curRingData[3];
09814    int receivedRingT;
09815    int counter1;
09816    int counter;
09817    int samples = 0;
09818    struct ast_smdi_md_message *smdi_msg = NULL;
09819    int flags = 0;
09820    int i;
09821    int timeout;
09822    int getforward = 0;
09823    char *s1, *s2;
09824    int len = 0;
09825    int res;
09826    int idx;
09827 
09828    ast_mutex_lock(&ss_thread_lock);
09829    ss_thread_count++;
09830    ast_mutex_unlock(&ss_thread_lock);
09831    /* in the bizarre case where the channel has become a zombie before we
09832       even get started here, abort safely
09833    */
09834    if (!p) {
09835       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09836       ast_hangup(chan);
09837       goto quit;
09838    }
09839    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09840    idx = dahdi_get_index(chan, p, 1);
09841    if (idx < 0) {
09842       ast_log(LOG_WARNING, "Huh?\n");
09843       ast_hangup(chan);
09844       goto quit;
09845    }
09846    if (p->dsp)
09847       ast_dsp_digitreset(p->dsp);
09848    switch (p->sig) {
09849    case SIG_FEATD:
09850    case SIG_FEATDMF:
09851    case SIG_FEATDMF_TA:
09852    case SIG_E911:
09853    case SIG_FGC_CAMAMF:
09854    case SIG_FEATB:
09855    case SIG_EMWINK:
09856    case SIG_SF_FEATD:
09857    case SIG_SF_FEATDMF:
09858    case SIG_SF_FEATB:
09859    case SIG_SFWINK:
09860       if (dahdi_wink(p, idx))
09861          goto quit;
09862       /* Fall through */
09863    case SIG_EM:
09864    case SIG_EM_E1:
09865    case SIG_SF:
09866    case SIG_FGC_CAMA:
09867       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09868       if (p->dsp)
09869          ast_dsp_digitreset(p->dsp);
09870       /* set digit mode appropriately */
09871       if (p->dsp) {
09872          if (NEED_MFDETECT(p))
09873             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09874          else
09875             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09876       }
09877       memset(dtmfbuf, 0, sizeof(dtmfbuf));
09878       /* Wait for the first digit only if immediate=no */
09879       if (!p->immediate)
09880          /* Wait for the first digit (up to 5 seconds). */
09881          res = ast_waitfordigit(chan, 5000);
09882       else
09883          res = 0;
09884       if (res > 0) {
09885          /* save first char */
09886          dtmfbuf[0] = res;
09887          switch (p->sig) {
09888          case SIG_FEATD:
09889          case SIG_SF_FEATD:
09890             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09891             if (res > 0)
09892                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09893             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09894             break;
09895          case SIG_FEATDMF_TA:
09896             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09897             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09898             if (dahdi_wink(p, idx)) goto quit;
09899             dtmfbuf[0] = 0;
09900             /* Wait for the first digit (up to 5 seconds). */
09901             res = ast_waitfordigit(chan, 5000);
09902             if (res <= 0) break;
09903             dtmfbuf[0] = res;
09904             /* fall through intentionally */
09905          case SIG_FEATDMF:
09906          case SIG_E911:
09907          case SIG_FGC_CAMAMF:
09908          case SIG_SF_FEATDMF:
09909             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09910             /* if international caca, do it again to get real ANO */
09911             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
09912             {
09913                if (dahdi_wink(p, idx)) goto quit;
09914                dtmfbuf[0] = 0;
09915                /* Wait for the first digit (up to 5 seconds). */
09916                res = ast_waitfordigit(chan, 5000);
09917                if (res <= 0) break;
09918                dtmfbuf[0] = res;
09919                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09920             }
09921             if (res > 0) {
09922                /* if E911, take off hook */
09923                if (p->sig == SIG_E911)
09924                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09925                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
09926             }
09927             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09928             break;
09929          case SIG_FEATB:
09930          case SIG_SF_FEATB:
09931             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09932             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09933             break;
09934          case SIG_EMWINK:
09935             /* if we received a '*', we are actually receiving Feature Group D
09936                dial syntax, so use that mode; otherwise, fall through to normal
09937                mode
09938             */
09939             if (res == '*') {
09940                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09941                if (res > 0)
09942                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09943                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09944                break;
09945             }
09946          default:
09947             /* If we got the first digit, get the rest */
09948             len = 1;
09949             dtmfbuf[len] = '\0';
09950             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09951                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09952                   timeout = matchdigittimeout;
09953                } else {
09954                   timeout = gendigittimeout;
09955                }
09956                res = ast_waitfordigit(chan, timeout);
09957                if (res < 0) {
09958                   ast_debug(1, "waitfordigit returned < 0...\n");
09959                   ast_hangup(chan);
09960                   goto quit;
09961                } else if (res) {
09962                   dtmfbuf[len++] = res;
09963                   dtmfbuf[len] = '\0';
09964                } else {
09965                   break;
09966                }
09967             }
09968             break;
09969          }
09970       }
09971       if (res == -1) {
09972          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
09973          ast_hangup(chan);
09974          goto quit;
09975       } else if (res < 0) {
09976          ast_debug(1, "Got hung up before digits finished\n");
09977          ast_hangup(chan);
09978          goto quit;
09979       }
09980 
09981       if (p->sig == SIG_FGC_CAMA) {
09982          char anibuf[100];
09983 
09984          if (ast_safe_sleep(chan,1000) == -1) {
09985             ast_hangup(chan);
09986             goto quit;
09987          }
09988          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09989          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09990          res = my_getsigstr(chan, anibuf, "#", 10000);
09991          if ((res > 0) && (strlen(anibuf) > 2)) {
09992             if (anibuf[strlen(anibuf) - 1] == '#')
09993                anibuf[strlen(anibuf) - 1] = 0;
09994             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
09995          }
09996          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09997       }
09998 
09999       ast_copy_string(exten, dtmfbuf, sizeof(exten));
10000       if (ast_strlen_zero(exten))
10001          ast_copy_string(exten, "s", sizeof(exten));
10002       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10003          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10004          if (exten[0] == '*') {
10005             char *stringp=NULL;
10006             ast_copy_string(exten2, exten, sizeof(exten2));
10007             /* Parse out extension and callerid */
10008             stringp=exten2 +1;
10009             s1 = strsep(&stringp, "*");
10010             s2 = strsep(&stringp, "*");
10011             if (s2) {
10012                if (!ast_strlen_zero(p->cid_num))
10013                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10014                else
10015                   ast_set_callerid(chan, s1, NULL, s1);
10016                ast_copy_string(exten, s2, sizeof(exten));
10017             } else
10018                ast_copy_string(exten, s1, sizeof(exten));
10019          } else if (p->sig == SIG_FEATD)
10020             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10021       }
10022       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10023          if (exten[0] == '*') {
10024             char *stringp=NULL;
10025             ast_copy_string(exten2, exten, sizeof(exten2));
10026             /* Parse out extension and callerid */
10027             stringp=exten2 +1;
10028             s1 = strsep(&stringp, "#");
10029             s2 = strsep(&stringp, "#");
10030             if (s2) {
10031                if (!ast_strlen_zero(p->cid_num))
10032                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10033                else
10034                   if (*(s1 + 2))
10035                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10036                ast_copy_string(exten, s2 + 1, sizeof(exten));
10037             } else
10038                ast_copy_string(exten, s1 + 2, sizeof(exten));
10039          } else
10040             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10041       }
10042       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10043          if (exten[0] == '*') {
10044             char *stringp=NULL;
10045             ast_copy_string(exten2, exten, sizeof(exten2));
10046             /* Parse out extension and callerid */
10047             stringp=exten2 +1;
10048             s1 = strsep(&stringp, "#");
10049             s2 = strsep(&stringp, "#");
10050             if (s2 && (*(s2 + 1) == '0')) {
10051                if (*(s2 + 2))
10052                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10053             }
10054             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10055             else ast_copy_string(exten, "911", sizeof(exten));
10056          } else
10057             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10058       }
10059       if (p->sig == SIG_FEATB) {
10060          if (exten[0] == '*') {
10061             char *stringp=NULL;
10062             ast_copy_string(exten2, exten, sizeof(exten2));
10063             /* Parse out extension and callerid */
10064             stringp=exten2 +1;
10065             s1 = strsep(&stringp, "#");
10066             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10067          } else
10068             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10069       }
10070       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10071          dahdi_wink(p, idx);
10072          /* some switches require a minimum guard time between
10073             the last FGD wink and something that answers
10074             immediately. This ensures it */
10075          if (ast_safe_sleep(chan, 100)) {
10076             ast_hangup(chan);
10077             goto quit;
10078          }
10079       }
10080       dahdi_enable_ec(p);
10081       if (NEED_MFDETECT(p)) {
10082          if (p->dsp) {
10083             if (!p->hardwaredtmf)
10084                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10085             else {
10086                ast_dsp_free(p->dsp);
10087                p->dsp = NULL;
10088             }
10089          }
10090       }
10091 
10092       if (ast_exists_extension(chan, chan->context, exten, 1,
10093          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10094          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10095          if (p->dsp) ast_dsp_digitreset(p->dsp);
10096          res = ast_pbx_run(chan);
10097          if (res) {
10098             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10099             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10100          }
10101          goto quit;
10102       } else {
10103          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10104          sleep(2);
10105          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10106          if (res < 0)
10107             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10108          else
10109             sleep(1);
10110          res = ast_streamfile(chan, "ss-noservice", chan->language);
10111          if (res >= 0)
10112             ast_waitstream(chan, "");
10113          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10114          ast_hangup(chan);
10115          goto quit;
10116       }
10117       break;
10118    case SIG_FXOLS:
10119    case SIG_FXOGS:
10120    case SIG_FXOKS:
10121       /* Read the first digit */
10122       timeout = firstdigittimeout;
10123       /* If starting a threeway call, never timeout on the first digit so someone
10124          can use flash-hook as a "hold" feature */
10125       if (p->subs[SUB_THREEWAY].owner)
10126          timeout = 999999;
10127       while (len < AST_MAX_EXTENSION-1) {
10128          /* Read digit unless it's supposed to be immediate, in which case the
10129             only answer is 's' */
10130          if (p->immediate)
10131             res = 's';
10132          else
10133             res = ast_waitfordigit(chan, timeout);
10134          timeout = 0;
10135          if (res < 0) {
10136             ast_debug(1, "waitfordigit returned < 0...\n");
10137             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10138             ast_hangup(chan);
10139             goto quit;
10140          } else if (res) {
10141             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10142             exten[len++]=res;
10143             exten[len] = '\0';
10144          }
10145          if (!ast_ignore_pattern(chan->context, exten))
10146             tone_zone_play_tone(p->subs[idx].dfd, -1);
10147          else
10148             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10149          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10150             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10151                if (getforward) {
10152                   /* Record this as the forwarding extension */
10153                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10154                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10155                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10156                   if (res)
10157                      break;
10158                   usleep(500000);
10159                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10160                   sleep(1);
10161                   memset(exten, 0, sizeof(exten));
10162                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10163                   len = 0;
10164                   getforward = 0;
10165                } else {
10166                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10167                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10168                   if (!ast_strlen_zero(p->cid_num)) {
10169                      if (!p->hidecallerid)
10170                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10171                      else
10172                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10173                   }
10174                   if (!ast_strlen_zero(p->cid_name)) {
10175                      if (!p->hidecallerid)
10176                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10177                   }
10178                   ast_setstate(chan, AST_STATE_RING);
10179                   dahdi_enable_ec(p);
10180                   res = ast_pbx_run(chan);
10181                   if (res) {
10182                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10183                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10184                   }
10185                   goto quit;
10186                }
10187             } else {
10188                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10189                   so just set the timeout to matchdigittimeout and wait some more */
10190                timeout = matchdigittimeout;
10191             }
10192          } else if (res == 0) {
10193             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10194             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10195             dahdi_wait_event(p->subs[idx].dfd);
10196             ast_hangup(chan);
10197             goto quit;
10198          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10199             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10200             /* Disable call waiting if enabled */
10201             p->callwaiting = 0;
10202             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10203             if (res) {
10204                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10205                   chan->name, strerror(errno));
10206             }
10207             len = 0;
10208             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10209             memset(exten, 0, sizeof(exten));
10210             timeout = firstdigittimeout;
10211 
10212          } else if (!strcmp(exten,ast_pickup_ext())) {
10213             /* Scan all channels and see if there are any
10214              * ringing channels that have call groups
10215              * that equal this channels pickup group
10216              */
10217             if (idx == SUB_REAL) {
10218                /* Switch us from Third call to Call Wait */
10219                if (p->subs[SUB_THREEWAY].owner) {
10220                   /* If you make a threeway call and the *8# a call, it should actually
10221                      look like a callwait */
10222                   alloc_sub(p, SUB_CALLWAIT);
10223                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10224                   unalloc_sub(p, SUB_THREEWAY);
10225                }
10226                dahdi_enable_ec(p);
10227                if (ast_pickup_call(chan)) {
10228                   ast_debug(1, "No call pickup possible...\n");
10229                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10230                   dahdi_wait_event(p->subs[idx].dfd);
10231                }
10232                ast_hangup(chan);
10233                goto quit;
10234             } else {
10235                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10236                ast_hangup(chan);
10237                goto quit;
10238             }
10239 
10240          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10241             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10242             /* Disable Caller*ID if enabled */
10243             p->hidecallerid = 1;
10244             ast_party_number_free(&chan->caller.id.number);
10245             ast_party_number_init(&chan->caller.id.number);
10246             ast_party_name_free(&chan->caller.id.name);
10247             ast_party_name_init(&chan->caller.id.name);
10248             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10249             if (res) {
10250                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10251                   chan->name, strerror(errno));
10252             }
10253             len = 0;
10254             memset(exten, 0, sizeof(exten));
10255             timeout = firstdigittimeout;
10256          } else if (p->callreturn && !strcmp(exten, "*69")) {
10257             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10258             break;
10259          } else if (!strcmp(exten, "*78")) {
10260             dahdi_dnd(p, 1);
10261             /* Do not disturb */
10262             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10263             getforward = 0;
10264             memset(exten, 0, sizeof(exten));
10265             len = 0;
10266          } else if (!strcmp(exten, "*79")) {
10267             dahdi_dnd(p, 0);
10268             /* Do not disturb */
10269             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10270             getforward = 0;
10271             memset(exten, 0, sizeof(exten));
10272             len = 0;
10273          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10274             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10275             getforward = 1;
10276             memset(exten, 0, sizeof(exten));
10277             len = 0;
10278          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10279             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10280             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10281             memset(p->call_forward, 0, sizeof(p->call_forward));
10282             getforward = 0;
10283             memset(exten, 0, sizeof(exten));
10284             len = 0;
10285          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10286                   p->subs[SUB_THREEWAY].owner &&
10287                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10288             /* This is a three way call, the main call being a real channel,
10289                and we're parking the first call. */
10290             ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10291                chan, exten, chan->context, 0, NULL);
10292             ast_verb(3, "Parking call to '%s'\n", chan->name);
10293             break;
10294          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10295             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10296             /* Enable Caller*ID if enabled */
10297             p->hidecallerid = 0;
10298             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10299             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10300             if (res) {
10301                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10302                   chan->name, strerror(errno));
10303             }
10304             len = 0;
10305             memset(exten, 0, sizeof(exten));
10306             timeout = firstdigittimeout;
10307          } else if (!strcmp(exten, "*0")) {
10308             struct ast_channel *nbridge =
10309                p->subs[SUB_THREEWAY].owner;
10310             struct dahdi_pvt *pbridge = NULL;
10311             /* set up the private struct of the bridged one, if any */
10312             if (nbridge && ast_bridged_channel(nbridge))
10313                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10314             if (nbridge && pbridge &&
10315                (nbridge->tech == &dahdi_tech) &&
10316                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10317                ISTRUNK(pbridge)) {
10318                int func = DAHDI_FLASH;
10319                /* Clear out the dial buffer */
10320                p->dop.dialstr[0] = '\0';
10321                /* flash hookswitch */
10322                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10323                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10324                      nbridge->name, strerror(errno));
10325                }
10326                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10327                unalloc_sub(p, SUB_THREEWAY);
10328                p->owner = p->subs[SUB_REAL].owner;
10329                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10330                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10331                ast_hangup(chan);
10332                goto quit;
10333             } else {
10334                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10335                dahdi_wait_event(p->subs[idx].dfd);
10336                tone_zone_play_tone(p->subs[idx].dfd, -1);
10337                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10338                unalloc_sub(p, SUB_THREEWAY);
10339                p->owner = p->subs[SUB_REAL].owner;
10340                ast_hangup(chan);
10341                goto quit;
10342             }
10343          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10344             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10345             && !canmatch_featurecode(exten)) {
10346             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10347                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10348                chan->context);
10349             break;
10350          }
10351          if (!timeout)
10352             timeout = gendigittimeout;
10353          if (len && !ast_ignore_pattern(chan->context, exten))
10354             tone_zone_play_tone(p->subs[idx].dfd, -1);
10355       }
10356       break;
10357    case SIG_FXSLS:
10358    case SIG_FXSGS:
10359    case SIG_FXSKS:
10360       /* check for SMDI messages */
10361       if (p->use_smdi && p->smdi_iface) {
10362          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10363 
10364          if (smdi_msg != NULL) {
10365             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10366 
10367             if (smdi_msg->type == 'B')
10368                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10369             else if (smdi_msg->type == 'N')
10370                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10371 
10372             ast_debug(1, "Received SMDI message on %s\n", chan->name);
10373          } else {
10374             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10375          }
10376       }
10377 
10378       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10379          number = smdi_msg->calling_st;
10380 
10381       /* If we want caller id, we're in a prering state due to a polarity reversal
10382        * and we're set to use a polarity reversal to trigger the start of caller id,
10383        * grab the caller id and wait for ringing to start... */
10384       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10385                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10386          /* If set to use DTMF CID signalling, listen for DTMF */
10387          if (p->cid_signalling == CID_SIG_DTMF) {
10388             int k = 0;
10389             cs = NULL;
10390             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10391             dahdi_setlinear(p->subs[idx].dfd, 0);
10392             /*
10393              * We are the only party interested in the Rx stream since
10394              * we have not answered yet.  We don't need or even want DTMF
10395              * emulation.  The DTMF digits can come so fast that emulation
10396              * can drop some of them.
10397              */
10398             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10399             res = 4000;/* This is a typical OFF time between rings. */
10400             for (;;) {
10401                struct ast_frame *f;
10402                res = ast_waitfor(chan, res);
10403                if (res <= 0) {
10404                   /*
10405                    * We do not need to restore the dahdi_setlinear()
10406                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10407                    * are hanging up the channel.
10408                    */
10409                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10410                      "Exiting simple switch\n");
10411                   ast_hangup(chan);
10412                   goto quit;
10413                }
10414                f = ast_read(chan);
10415                if (!f)
10416                   break;
10417                if (f->frametype == AST_FRAME_DTMF) {
10418                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10419                      dtmfbuf[k++] = f->subclass.integer;
10420                   }
10421                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10422                   res = 4000;/* This is a typical OFF time between rings. */
10423                }
10424                ast_frfree(f);
10425                if (chan->_state == AST_STATE_RING ||
10426                   chan->_state == AST_STATE_RINGING)
10427                   break; /* Got ring */
10428             }
10429             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10430             dtmfbuf[k] = '\0';
10431             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10432             /* Got cid and ring. */
10433             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10434             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10435             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10436             /* If first byte is NULL, we have no cid */
10437             if (!ast_strlen_zero(dtmfcid))
10438                number = dtmfcid;
10439             else
10440                number = NULL;
10441          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10442          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10443             cs = callerid_new(p->cid_signalling);
10444             if (cs) {
10445                samples = 0;
10446 #if 1
10447                bump_gains(p);
10448 #endif
10449                /* Take out of linear mode for Caller*ID processing */
10450                dahdi_setlinear(p->subs[idx].dfd, 0);
10451 
10452                /* First we wait and listen for the Caller*ID */
10453                for (;;) {
10454                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10455                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10456                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10457                      callerid_free(cs);
10458                      ast_hangup(chan);
10459                      goto quit;
10460                   }
10461                   if (i & DAHDI_IOMUX_SIGEVENT) {
10462                      res = dahdi_get_event(p->subs[idx].dfd);
10463                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10464                      if (res == DAHDI_EVENT_NOALARM) {
10465                         p->inalarm = 0;
10466                      }
10467 
10468                      if (p->cid_signalling == CID_SIG_V23_JP) {
10469                         if (res == DAHDI_EVENT_RINGBEGIN) {
10470                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10471                            usleep(1);
10472                         }
10473                      } else {
10474                         res = 0;
10475                         break;
10476                      }
10477                   } else if (i & DAHDI_IOMUX_READ) {
10478                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10479                      if (res < 0) {
10480                         if (errno != ELAST) {
10481                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10482                            callerid_free(cs);
10483                            ast_hangup(chan);
10484                            goto quit;
10485                         }
10486                         break;
10487                      }
10488                      samples += res;
10489 
10490                      if (p->cid_signalling == CID_SIG_V23_JP) {
10491                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10492                      } else {
10493                         res = callerid_feed(cs, buf, res, AST_LAW(p));
10494                      }
10495                      if (res < 0) {
10496                         /*
10497                          * The previous diagnostic message output likely
10498                          * explains why it failed.
10499                          */
10500                         ast_log(LOG_WARNING,
10501                            "Failed to decode CallerID on channel '%s'\n",
10502                            chan->name);
10503                         break;
10504                      } else if (res)
10505                         break;
10506                      else if (samples > (8000 * 10))
10507                         break;
10508                   }
10509                }
10510                if (res == 1) {
10511                   callerid_get(cs, &name, &number, &flags);
10512                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10513                }
10514 
10515                if (p->cid_signalling == CID_SIG_V23_JP) {
10516                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10517                   usleep(1);
10518                }
10519 
10520                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10521                res = 4000;/* This is a typical OFF time between rings. */
10522                for (;;) {
10523                   struct ast_frame *f;
10524                   res = ast_waitfor(chan, res);
10525                   if (res <= 0) {
10526                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10527                         "Exiting simple switch\n");
10528                      ast_hangup(chan);
10529                      goto quit;
10530                   }
10531                   if (!(f = ast_read(chan))) {
10532                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10533                      ast_hangup(chan);
10534                      goto quit;
10535                   }
10536                   ast_frfree(f);
10537                   if (chan->_state == AST_STATE_RING ||
10538                      chan->_state == AST_STATE_RINGING)
10539                      break; /* Got ring */
10540                }
10541 
10542                /* We must have a ring by now, so, if configured, lets try to listen for
10543                 * distinctive ringing */
10544                if (p->usedistinctiveringdetection) {
10545                   len = 0;
10546                   distMatches = 0;
10547                   /* Clear the current ring data array so we don't have old data in it. */
10548                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10549                      curRingData[receivedRingT] = 0;
10550                   receivedRingT = 0;
10551                   counter = 0;
10552                   counter1 = 0;
10553                   /* Check to see if context is what it should be, if not set to be. */
10554                   if (strcmp(p->context,p->defcontext) != 0) {
10555                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10556                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10557                   }
10558 
10559                   for (;;) {
10560                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10561                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10562                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10563                         callerid_free(cs);
10564                         ast_hangup(chan);
10565                         goto quit;
10566                      }
10567                      if (i & DAHDI_IOMUX_SIGEVENT) {
10568                         res = dahdi_get_event(p->subs[idx].dfd);
10569                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10570                         if (res == DAHDI_EVENT_NOALARM) {
10571                            p->inalarm = 0;
10572                         }
10573                         res = 0;
10574                         /* Let us detect distinctive ring */
10575 
10576                         curRingData[receivedRingT] = p->ringt;
10577 
10578                         if (p->ringt < p->ringt_base/2)
10579                            break;
10580                         /* Increment the ringT counter so we can match it against
10581                            values in chan_dahdi.conf for distinctive ring */
10582                         if (++receivedRingT == ARRAY_LEN(curRingData))
10583                            break;
10584                      } else if (i & DAHDI_IOMUX_READ) {
10585                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10586                         if (res < 0) {
10587                            if (errno != ELAST) {
10588                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10589                               callerid_free(cs);
10590                               ast_hangup(chan);
10591                               goto quit;
10592                            }
10593                            break;
10594                         }
10595                         if (p->ringt > 0) {
10596                            if (!(--p->ringt)) {
10597                               res = -1;
10598                               break;
10599                            }
10600                         }
10601                      }
10602                   }
10603                      /* this only shows up if you have n of the dring patterns filled in */
10604                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10605                   for (counter = 0; counter < 3; counter++) {
10606                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10607                      channel */
10608                      distMatches = 0;
10609                      for (counter1 = 0; counter1 < 3; counter1++) {
10610                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10611                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10612                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10613                            curRingData[counter1]);
10614                            distMatches++;
10615                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10616                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10617                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10618                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10619                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10620                            distMatches++;
10621                         }
10622                      }
10623 
10624                      if (distMatches == 3) {
10625                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10626                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10627                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10628                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10629                         break;
10630                      }
10631                   }
10632                }
10633                /* Restore linear mode (if appropriate) for Caller*ID processing */
10634                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10635 #if 1
10636                restore_gains(p);
10637 #endif
10638             } else
10639                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10640          } else {
10641             ast_log(LOG_WARNING, "Channel %s in prering "
10642                "state, but I have nothing to do. "
10643                "Terminating simple switch, should be "
10644                "restarted by the actual ring.\n",
10645                chan->name);
10646             ast_hangup(chan);
10647             goto quit;
10648          }
10649       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10650          if (p->cid_signalling == CID_SIG_DTMF) {
10651             int k = 0;
10652             cs = NULL;
10653             dahdi_setlinear(p->subs[idx].dfd, 0);
10654             res = 2000;
10655             for (;;) {
10656                struct ast_frame *f;
10657                res = ast_waitfor(chan, res);
10658                if (res <= 0) {
10659                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10660                      "Exiting simple switch\n");
10661                   ast_hangup(chan);
10662                   goto quit;
10663                }
10664                f = ast_read(chan);
10665                if (!f) {
10666                   /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10667                   ast_hangup(chan);
10668                   goto quit;
10669                }
10670                if (f->frametype == AST_FRAME_DTMF) {
10671                   dtmfbuf[k++] = f->subclass.integer;
10672                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10673                   res = 2000;
10674                }
10675                ast_frfree(f);
10676 
10677                if (p->ringt_base == p->ringt)
10678                   break;
10679             }
10680             dtmfbuf[k] = '\0';
10681             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10682             /* Got cid and ring. */
10683             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10684             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10685                dtmfcid, flags);
10686             /* If first byte is NULL, we have no cid */
10687             if (!ast_strlen_zero(dtmfcid))
10688                number = dtmfcid;
10689             else
10690                number = NULL;
10691             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10692          } else {
10693             /* FSK Bell202 callerID */
10694             cs = callerid_new(p->cid_signalling);
10695             if (cs) {
10696 #if 1
10697                bump_gains(p);
10698 #endif
10699                samples = 0;
10700                len = 0;
10701                distMatches = 0;
10702                /* Clear the current ring data array so we don't have old data in it. */
10703                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10704                   curRingData[receivedRingT] = 0;
10705                receivedRingT = 0;
10706                counter = 0;
10707                counter1 = 0;
10708                /* Check to see if context is what it should be, if not set to be. */
10709                if (strcmp(p->context,p->defcontext) != 0) {
10710                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10711                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10712                }
10713 
10714                /* Take out of linear mode for Caller*ID processing */
10715                dahdi_setlinear(p->subs[idx].dfd, 0);
10716                for (;;) {
10717                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10718                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10719                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10720                      callerid_free(cs);
10721                      ast_hangup(chan);
10722                      goto quit;
10723                   }
10724                   if (i & DAHDI_IOMUX_SIGEVENT) {
10725                      res = dahdi_get_event(p->subs[idx].dfd);
10726                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10727                      if (res == DAHDI_EVENT_NOALARM) {
10728                         p->inalarm = 0;
10729                      }
10730                      /* If we get a PR event, they hung up while processing calerid */
10731                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10732                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10733                         p->polarity = POLARITY_IDLE;
10734                         callerid_free(cs);
10735                         ast_hangup(chan);
10736                         goto quit;
10737                      }
10738                      res = 0;
10739                      /* Let us detect callerid when the telco uses distinctive ring */
10740 
10741                      curRingData[receivedRingT] = p->ringt;
10742 
10743                      if (p->ringt < p->ringt_base/2)
10744                         break;
10745                      /* Increment the ringT counter so we can match it against
10746                         values in chan_dahdi.conf for distinctive ring */
10747                      if (++receivedRingT == ARRAY_LEN(curRingData))
10748                         break;
10749                   } else if (i & DAHDI_IOMUX_READ) {
10750                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10751                      if (res < 0) {
10752                         if (errno != ELAST) {
10753                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10754                            callerid_free(cs);
10755                            ast_hangup(chan);
10756                            goto quit;
10757                         }
10758                         break;
10759                      }
10760                      if (p->ringt > 0) {
10761                         if (!(--p->ringt)) {
10762                            res = -1;
10763                            break;
10764                         }
10765                      }
10766                      samples += res;
10767                      res = callerid_feed(cs, buf, res, AST_LAW(p));
10768                      if (res < 0) {
10769                         /*
10770                          * The previous diagnostic message output likely
10771                          * explains why it failed.
10772                          */
10773                         ast_log(LOG_WARNING,
10774                            "Failed to decode CallerID on channel '%s'\n",
10775                            chan->name);
10776                         break;
10777                      } else if (res)
10778                         break;
10779                      else if (samples > (8000 * 10))
10780                         break;
10781                   }
10782                }
10783                if (res == 1) {
10784                   callerid_get(cs, &name, &number, &flags);
10785                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10786                }
10787                if (distinctiveringaftercid == 1) {
10788                   /* Clear the current ring data array so we don't have old data in it. */
10789                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10790                      curRingData[receivedRingT] = 0;
10791                   }
10792                   receivedRingT = 0;
10793                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10794                   for (;;) {
10795                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10796                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10797                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10798                         callerid_free(cs);
10799                         ast_hangup(chan);
10800                         goto quit;
10801                      }
10802                      if (i & DAHDI_IOMUX_SIGEVENT) {
10803                         res = dahdi_get_event(p->subs[idx].dfd);
10804                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10805                         if (res == DAHDI_EVENT_NOALARM) {
10806                            p->inalarm = 0;
10807                         }
10808                         res = 0;
10809                         /* Let us detect callerid when the telco uses distinctive ring */
10810 
10811                         curRingData[receivedRingT] = p->ringt;
10812 
10813                         if (p->ringt < p->ringt_base/2)
10814                            break;
10815                         /* Increment the ringT counter so we can match it against
10816                            values in chan_dahdi.conf for distinctive ring */
10817                         if (++receivedRingT == ARRAY_LEN(curRingData))
10818                            break;
10819                      } else if (i & DAHDI_IOMUX_READ) {
10820                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10821                         if (res < 0) {
10822                            if (errno != ELAST) {
10823                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10824                               callerid_free(cs);
10825                               ast_hangup(chan);
10826                               goto quit;
10827                            }
10828                            break;
10829                         }
10830                         if (p->ringt > 0) {
10831                            if (!(--p->ringt)) {
10832                               res = -1;
10833                               break;
10834                            }
10835                         }
10836                      }
10837                   }
10838                }
10839                if (p->usedistinctiveringdetection) {
10840                   /* this only shows up if you have n of the dring patterns filled in */
10841                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10842 
10843                   for (counter = 0; counter < 3; counter++) {
10844                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10845                      channel */
10846                      /* this only shows up if you have n of the dring patterns filled in */
10847                      ast_verb(3, "Checking %d,%d,%d\n",
10848                            p->drings.ringnum[counter].ring[0],
10849                            p->drings.ringnum[counter].ring[1],
10850                            p->drings.ringnum[counter].ring[2]);
10851                      distMatches = 0;
10852                      for (counter1 = 0; counter1 < 3; counter1++) {
10853                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10854                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10855                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10856                            curRingData[counter1]);
10857                            distMatches++;
10858                         }
10859                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10860                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10861                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10862                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10863                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10864                            distMatches++;
10865                         }
10866                      }
10867                      if (distMatches == 3) {
10868                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10869                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10870                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10871                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10872                         break;
10873                      }
10874                   }
10875                }
10876                /* Restore linear mode (if appropriate) for Caller*ID processing */
10877                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10878 #if 1
10879                restore_gains(p);
10880 #endif
10881                if (res < 0) {
10882                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10883                }
10884             } else
10885                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10886          }
10887       } else
10888          cs = NULL;
10889 
10890       if (number)
10891          ast_shrink_phone_number(number);
10892       ast_set_callerid(chan, number, name, number);
10893 
10894       if (smdi_msg)
10895          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
10896 
10897       if (cs)
10898          callerid_free(cs);
10899 
10900       my_handle_notify_message(chan, p, flags, -1);
10901 
10902       ast_setstate(chan, AST_STATE_RING);
10903       chan->rings = 1;
10904       p->ringt = p->ringt_base;
10905       res = ast_pbx_run(chan);
10906       if (res) {
10907          ast_hangup(chan);
10908          ast_log(LOG_WARNING, "PBX exited non-zero\n");
10909       }
10910       goto quit;
10911    default:
10912       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10913       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10914       if (res < 0)
10915             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10916    }
10917    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10918    if (res < 0)
10919          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10920    ast_hangup(chan);
10921 quit:
10922    ast_mutex_lock(&ss_thread_lock);
10923    ss_thread_count--;
10924    ast_cond_signal(&ss_thread_complete);
10925    ast_mutex_unlock(&ss_thread_lock);
10926    return NULL;
10927 }

static int analog_tone_to_dahditone ( enum analog_tone  tone  )  [static]

Definition at line 1620 of file chan_dahdi.c.

References ANALOG_TONE_CONGESTION, ANALOG_TONE_DIALRECALL, ANALOG_TONE_DIALTONE, ANALOG_TONE_INFO, ANALOG_TONE_RINGTONE, and ANALOG_TONE_STUTTER.

Referenced by my_play_tone().

01621 {
01622    switch (tone) {
01623    case ANALOG_TONE_RINGTONE:
01624       return DAHDI_TONE_RINGTONE;
01625    case ANALOG_TONE_STUTTER:
01626       return DAHDI_TONE_STUTTER;
01627    case ANALOG_TONE_CONGESTION:
01628       return DAHDI_TONE_CONGESTION;
01629    case ANALOG_TONE_DIALTONE:
01630       return DAHDI_TONE_DIALTONE;
01631    case ANALOG_TONE_DIALRECALL:
01632       return DAHDI_TONE_DIALRECALL;
01633    case ANALOG_TONE_INFO:
01634       return DAHDI_TONE_INFO;
01635    default:
01636       return -1;
01637    }
01638 }

static int analogsub_to_dahdisub ( enum analog_sub  analogsub  )  [static]

Definition at line 1640 of file chan_dahdi.c.

References ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL, ANALOG_SUB_THREEWAY, ast_log(), LOG_ERROR, SUB_CALLWAIT, SUB_REAL, and SUB_THREEWAY.

Referenced by my_allocate_sub(), my_conf_add(), my_conf_del(), my_dial_digits(), my_get_sub_fd(), my_handle_dtmf(), my_is_dialing(), my_new_analog_ast_channel(), my_play_tone(), my_set_inthreeway(), my_set_linear_mode(), my_swap_subchannels(), my_unallocate_sub(), and my_wink().

01641 {
01642    int index;
01643 
01644    switch (analogsub) {
01645    case ANALOG_SUB_REAL:
01646       index = SUB_REAL;
01647       break;
01648    case ANALOG_SUB_CALLWAIT:
01649       index = SUB_CALLWAIT;
01650       break;
01651    case ANALOG_SUB_THREEWAY:
01652       index = SUB_THREEWAY;
01653       break;
01654    default:
01655       ast_log(LOG_ERROR, "Unidentified sub!\n");
01656       index = SUB_REAL;
01657    }
01658 
01659    return index;
01660 }

AST_DATA_STRUCTURE ( dahdi_pvt  ,
DATA_EXPORT_DAHDI_PVT   
)

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

Definition at line 7580 of file chan_dahdi.c.

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

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

07581 {
07582    /* In order to transfer, we need at least one of the channels to
07583       actually be in a call bridge.  We can't conference two applications
07584       together (but then, why would we want to?) */
07585    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07586       /* The three-way person we're about to transfer to could still be in MOH, so
07587          stop if now if appropriate */
07588       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07589          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07590       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07591          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07592       }
07593       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07594          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07595       }
07596        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07597          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07598                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07599          return -1;
07600       }
07601       /* Orphan the channel after releasing the lock */
07602       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07603       unalloc_sub(p, SUB_THREEWAY);
07604    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07605       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07606       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07607          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07608       }
07609       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07610          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07611       }
07612       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07613          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07614                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07615          return -1;
07616       }
07617       /* Three-way is now the REAL */
07618       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07619       ast_channel_unlock(p->subs[SUB_REAL].owner);
07620       unalloc_sub(p, SUB_THREEWAY);
07621       /* Tell the caller not to hangup */
07622       return 1;
07623    } else {
07624       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07625          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07626       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07627       return -1;
07628    }
07629    return 0;
07630 }

static int available ( struct dahdi_pvt **  pvt,
int  is_specific_channel 
) [static]

Definition at line 13084 of file chan_dahdi.c.

References analog_available(), analog_lib_handles(), sig_pri_chan::chan_pvt, dahdi_pvt::inalarm, dahdi_pvt::locallyblocked, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2call, dahdi_pvt::oprmode, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::remotelyblocked, dahdi_pvt::sig, sig_pri_available(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, and sig_ss7_available().

Referenced by __ast_string_field_ptr_build_va(), ast_logger_register_level(), dahdi_request(), and sig_ss7_available().

13085 {
13086    struct dahdi_pvt *p = *pvt;
13087 
13088    if (p->inalarm)
13089       return 0;
13090 
13091    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13092       return analog_available(p->sig_pvt);
13093 
13094    switch (p->sig) {
13095 #if defined(HAVE_PRI)
13096    case SIG_PRI_LIB_HANDLE_CASES:
13097       {
13098          struct sig_pri_chan *pvt_chan;
13099          int res;
13100 
13101          pvt_chan = p->sig_pvt;
13102          res = sig_pri_available(&pvt_chan, is_specific_channel);
13103          *pvt = pvt_chan->chan_pvt;
13104          return res;
13105       }
13106 #endif   /* defined(HAVE_PRI) */
13107 #if defined(HAVE_SS7)
13108    case SIG_SS7:
13109       return sig_ss7_available(p->sig_pvt);
13110 #endif   /* defined(HAVE_SS7) */
13111    default:
13112       break;
13113    }
13114 
13115    if (p->locallyblocked || p->remotelyblocked) {
13116       return 0;
13117    }
13118 
13119    /* If no owner definitely available */
13120    if (!p->owner) {
13121 #ifdef HAVE_OPENR2
13122       /* Trust MFC/R2 */
13123       if (p->mfcr2) {
13124          if (p->mfcr2call) {
13125             return 0;
13126          } else {
13127             return 1;
13128          }
13129       }
13130 #endif
13131       return 1;
13132    }
13133 
13134    return 0;
13135 }

static int build_channels ( struct dahdi_chan_conf conf,
const char *  value,
int  reload,
int  lineno,
int *  found_pseudo 
) [static]

Definition at line 16700 of file chan_dahdi.c.

References ast_log(), ast_strdupa, ast_strlen_zero(), ast_verb, dahdi_chan_conf::chan, CHAN_PSEUDO, device2chan(), dahdi_chan_conf::ignore_failed_channels, dahdi_chan_conf::is_sig_auto, mkintf(), parse_spanchan(), dahdi_pvt::sig, sig2str, and strsep().

Referenced by process_dahdi().

16701 {
16702    char *c, *chan;
16703    char *subdir;
16704    int x, start, finish;
16705    struct dahdi_pvt *tmp;
16706 
16707    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16708       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16709       return -1;
16710    }
16711 
16712    c = ast_strdupa(value);
16713    c = parse_spanchan(c, &subdir);
16714 
16715    while ((chan = strsep(&c, ","))) {
16716       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16717          /* Range */
16718       } else if (sscanf(chan, "%30d", &start)) {
16719          /* Just one */
16720          finish = start;
16721       } else if (!strcasecmp(chan, "pseudo")) {
16722          finish = start = CHAN_PSEUDO;
16723          if (found_pseudo)
16724             *found_pseudo = 1;
16725       } else {
16726          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16727          return -1;
16728       }
16729       if (finish < start) {
16730          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16731          x = finish;
16732          finish = start;
16733          start = x;
16734       }
16735 
16736       for (x = start; x <= finish; x++) {
16737          char fn[PATH_MAX];
16738          int real_channel = x;
16739 
16740          if (!ast_strlen_zero(subdir)) {
16741             real_channel = device2chan(subdir, x, fn, sizeof(fn));
16742             if (real_channel < 0) {
16743                if (conf->ignore_failed_channels) {
16744                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16745                         subdir, x, real_channel);
16746                   continue;
16747                } else {
16748                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16749                         subdir, x, real_channel);
16750                   return -1;
16751                }
16752             }
16753          }
16754          tmp = mkintf(real_channel, conf, reload);
16755 
16756          if (tmp) {
16757             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16758          } else {
16759             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16760                   (reload == 1) ? "reconfigure" : "register", value);
16761             return -1;
16762          }
16763       }
16764    }
16765 
16766    return 0;
16767 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

Definition at line 5069 of file chan_dahdi.c.

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

Referenced by analog_ss_thread(), mwi_thread(), and my_start_cid_detect().

05070 {
05071    int res;
05072 
05073    /* Bump receive gain by value stored in cid_rxgain */
05074    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05075    if (res) {
05076       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05077       return -1;
05078    }
05079 
05080    return 0;
05081 }

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

Definition at line 10935 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by mwi_thread().

10936 {
10937    int x;
10938    int sum = 0;
10939 
10940    if (!len)
10941       return 0;
10942 
10943    for (x = 0; x < len; x++)
10944       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10945 
10946    return sum / len;
10947 }

static int canmatch_featurecode ( const char *  exten  )  [static]

Definition at line 9774 of file chan_dahdi.c.

References ast_pickup_ext(), and pickup_ext.

Referenced by analog_ss_thread().

09775 {
09776    int extlen = strlen(exten);
09777    const char *pickup_ext;
09778    if (!extlen) {
09779       return 1;
09780    }
09781    pickup_ext = ast_pickup_ext();
09782    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09783       return 1;
09784    }
09785    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09786    if (exten[0] == '*' && extlen < 3) {
09787       if (extlen == 1) {
09788          return 1;
09789       }
09790       /* "*0" should be processed before it gets here */
09791       switch (exten[1]) {
09792       case '6':
09793       case '7':
09794       case '8':
09795          return 1;
09796       }
09797    }
09798    return 0;
09799 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

Definition at line 7632 of file chan_dahdi.c.

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

Referenced by dahdi_handle_event(), and my_check_for_conference().

07633 {
07634    struct dahdi_confinfo ci;
07635    /* Fine if we already have a master, etc */
07636    if (p->master || (p->confno > -1))
07637       return 0;
07638    memset(&ci, 0, sizeof(ci));
07639    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07640       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07641       return 0;
07642    }
07643    /* If we have no master and don't have a confno, then
07644       if we're in a conference, it's probably a MeetMe room or
07645       some such, so don't let us 3-way out! */
07646    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07647       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07648       return 1;
07649    }
07650    return 0;
07651 }

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

Definition at line 14136 of file chan_dahdi.c.

References complete_span_helper().

Referenced by handle_pri_debug(), and handle_pri_show_span().

14137 {
14138    return complete_span_helper(line,word,pos,state,3);
14139 }

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

Definition at line 14115 of file chan_dahdi.c.

References asprintf, ast_log(), errno, dahdi_pri::pri, and pris.

Referenced by complete_span_4().

14116 {
14117    int which, span;
14118    char *ret = NULL;
14119 
14120    if (pos != rpos)
14121       return ret;
14122 
14123    for (which = span = 0; span < NUM_SPANS; span++) {
14124       if (pris[span].pri.pri && ++which > state) {
14125          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
14126             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14127          }
14128          break;
14129       }
14130    }
14131    return ret;
14132 }

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

Definition at line 4651 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 my_complete_conference_update(), my_conf_add(), and update_conf().

04652 {
04653    /* If the conference already exists, and we're already in it
04654       don't bother doing anything */
04655    struct dahdi_confinfo zi;
04656 
04657    memset(&zi, 0, sizeof(zi));
04658    zi.chan = 0;
04659 
04660    if (slavechannel > 0) {
04661       /* If we have only one slave, do a digital mon */
04662       zi.confmode = DAHDI_CONF_DIGITALMON;
04663       zi.confno = slavechannel;
04664    } else {
04665       if (!idx) {
04666          /* Real-side and pseudo-side both participate in conference */
04667          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04668             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04669       } else
04670          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04671       zi.confno = p->confno;
04672    }
04673    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04674       return 0;
04675    if (c->dfd < 0)
04676       return 0;
04677    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04678       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04679       return -1;
04680    }
04681    if (slavechannel < 1) {
04682       p->confno = zi.confno;
04683    }
04684    c->curconf = zi;
04685    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04686    return 0;
04687 }

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

Definition at line 4700 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(), my_conf_del(), and update_conf().

04701 {
04702    struct dahdi_confinfo zi;
04703    if (/* Can't delete if there's no dfd */
04704       (c->dfd < 0) ||
04705       /* Don't delete from the conference if it's not our conference */
04706       !isourconf(p, c)
04707       /* Don't delete if we don't think it's conferenced at all (implied) */
04708       ) return 0;
04709    memset(&zi, 0, sizeof(zi));
04710    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04711       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04712       return -1;
04713    }
04714    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04715    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04716    return 0;
04717 }

static struct ast_str* create_channel_name ( struct dahdi_pvt i,
int  is_outgoing,
char *  address 
) [static]

Definition at line 9433 of file chan_dahdi.c.

References ast_mutex_lock, ast_mutex_unlock, ast_random(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strlen_zero(), and CHAN_PSEUDO.

Referenced by dahdi_cc_callback(), and dahdi_new().

09437 {
09438    struct ast_str *chan_name;
09439    int x, y;
09440 
09441    /* Create the new channel name tail. */
09442    if (!(chan_name = ast_str_create(32))) {
09443       return NULL;
09444    }
09445    if (i->channel == CHAN_PSEUDO) {
09446       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09447 #if defined(HAVE_PRI)
09448    } else if (i->pri) {
09449       ast_mutex_lock(&i->pri->lock);
09450       y = ++i->pri->new_chan_seq;
09451       if (is_outgoing) {
09452          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09453          address[0] = '\0';
09454       } else if (ast_strlen_zero(i->cid_subaddr)) {
09455          /* Put in caller-id number only since there is no subaddress. */
09456          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09457       } else {
09458          /* Put in caller-id number and subaddress. */
09459          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09460             i->cid_subaddr, y);
09461       }
09462       ast_mutex_unlock(&i->pri->lock);
09463 #endif   /* defined(HAVE_PRI) */
09464    } else {
09465       y = 1;
09466       do {
09467          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09468          for (x = 0; x < 3; ++x) {
09469             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09470                i->subs[x].owner->name + 6)) {
09471                break;
09472             }
09473          }
09474          ++y;
09475       } while (x < 3);
09476    }
09477    return chan_name;
09478 }

static int dahdi_accept_r2_call_exec ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 5926 of file chan_dahdi.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_strlen_zero(), dahdi_tech, f, LOG_DEBUG, parse(), and ast_channel::tech.

Referenced by load_module().

05927 {
05928    /* data is whether to accept with charge or no charge */
05929    openr2_call_mode_t accept_mode;
05930    int res, timeout, maxloops;
05931    struct ast_frame *f;
05932    struct dahdi_pvt *p;
05933    char *parse;
05934    AST_DECLARE_APP_ARGS(args,
05935          AST_APP_ARG(charge);
05936    );
05937 
05938    if (ast_strlen_zero(data)) {
05939       ast_log(LOG_DEBUG, "No data sent to application!\n");
05940       return -1;
05941    }
05942 
05943    if (chan->tech != &dahdi_tech) {
05944       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05945       return -1;
05946    }
05947 
05948    p = (struct dahdi_pvt *)chan->tech_pvt;
05949    if (!p) {
05950       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
05951       return -1;
05952    }
05953 
05954    parse = ast_strdupa(data);
05955    AST_STANDARD_APP_ARGS(args, parse);
05956 
05957    if (ast_strlen_zero(args.charge)) {
05958       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
05959       return -1;
05960    }
05961 
05962    ast_mutex_lock(&p->lock);
05963    if (!p->mfcr2 || !p->mfcr2call) {
05964       ast_mutex_unlock(&p->lock);
05965       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
05966       return -1;
05967    }
05968 
05969    if (p->mfcr2_call_accepted) {
05970       ast_mutex_unlock(&p->lock);
05971       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
05972       return 0;
05973    }
05974    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
05975    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
05976       ast_mutex_unlock(&p->lock);
05977       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05978       return -1;
05979    }
05980    ast_mutex_unlock(&p->lock);
05981 
05982    res = 0;
05983    timeout = 100;
05984    maxloops = 50; /* wait up to 5 seconds */
05985    /* we need to read() until the call is accepted */
05986    while (maxloops > 0) {
05987       maxloops--;
05988       if (ast_check_hangup(chan)) {
05989          break;
05990       }
05991       res = ast_waitfor(chan, timeout);
05992       if (res < 0) {
05993          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
05994          res = -1;
05995          break;
05996       }
05997       if (res == 0) {
05998          continue;
05999       }
06000       f = ast_read(chan);
06001       if (!f) {
06002          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06003          res = -1;
06004          break;
06005       }
06006       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06007          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06008          ast_frfree(f);
06009          res = -1;
06010          break;
06011       }
06012       ast_frfree(f);
06013       ast_mutex_lock(&p->lock);
06014       if (p->mfcr2_call_accepted) {
06015          ast_mutex_unlock(&p->lock);
06016          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06017          break;
06018       }
06019       ast_mutex_unlock(&p->lock);
06020    }
06021    if (res == -1) {
06022       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06023    }
06024    return res;
06025 }

static void dahdi_ami_channel_event ( struct dahdi_pvt p,
struct ast_channel chan 
) [static]

Definition at line 2139 of file chan_dahdi.c.

References ast_manager_event, CHAN_PSEUDO, dahdi_pvt::channel, EVENT_FLAG_CALL, ast_channel::name, dahdi_pvt::span, and ast_channel::uniqueid.

Referenced by dahdi_new(), and my_ami_channel_event().

02140 {
02141    char ch_name[20];
02142 
02143    if (p->channel < CHAN_PSEUDO) {
02144       /* No B channel */
02145       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02146    } else if (p->channel == CHAN_PSEUDO) {
02147       /* Pseudo channel */
02148       strcpy(ch_name, "pseudo");
02149    } else {
02150       /* Real channel */
02151       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02152    }
02153    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02154       "Channel: %s\r\n"
02155       "Uniqueid: %s\r\n"
02156       "DAHDISpan: %d\r\n"
02157       "DAHDIChannel: %s\r\n",
02158       chan->name,
02159       chan->uniqueid,
02160       p->span,
02161       ch_name);
02162 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

Definition at line 6510 of file chan_dahdi.c.

References analog_answer(), analog_lib_handles(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_UP, dahdi_pvt::channel, dahdi_get_index, dahdi_r2_answer(), dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2_answer_pending, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::oprmode, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::sig, SIG_MFCR2, sig_pri_answer(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_answer(), SUB_REAL, and ast_channel::tech_pvt.

06511 {
06512    struct dahdi_pvt *p = ast->tech_pvt;
06513    int res = 0;
06514    int idx;
06515    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06516    ast_mutex_lock(&p->lock);
06517    idx = dahdi_get_index(ast, p, 0);
06518    if (idx < 0)
06519       idx = SUB_REAL;
06520    /* nothing to do if a radio channel */
06521    if ((p->radio || (p->oprmode < 0))) {
06522       ast_mutex_unlock(&p->lock);
06523       return 0;
06524    }
06525 
06526    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06527       res = analog_answer(p->sig_pvt, ast);
06528       ast_mutex_unlock(&p->lock);
06529       return res;
06530    }
06531 
06532    switch (p->sig) {
06533 #if defined(HAVE_PRI)
06534    case SIG_PRI_LIB_HANDLE_CASES:
06535       res = sig_pri_answer(p->sig_pvt, ast);
06536       break;
06537 #endif   /* defined(HAVE_PRI) */
06538 #if defined(HAVE_SS7)
06539    case SIG_SS7:
06540       res = sig_ss7_answer(p->sig_pvt, ast);
06541       break;
06542 #endif   /* defined(HAVE_SS7) */
06543 #ifdef HAVE_OPENR2
06544    case SIG_MFCR2:
06545       if (!p->mfcr2_call_accepted) {
06546          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06547             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06548          p->mfcr2_answer_pending = 1;
06549          if (p->mfcr2_charge_calls) {
06550             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06551             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06552          } else {
06553             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06554             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06555          }
06556       } else {
06557          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06558          dahdi_r2_answer(p);
06559       }
06560       break;
06561 #endif
06562    case 0:
06563       ast_mutex_unlock(&p->lock);
06564       return 0;
06565    default:
06566       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06567       res = -1;
06568       break;
06569    }
06570    ast_mutex_unlock(&p->lock);
06571    return res;
06572 }

static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause ( int  cause  )  [static]

Definition at line 6027 of file chan_dahdi.c.

References AST_CAUSE_CALL_REJECTED, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INTERWORKING, AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_USER_RESPONSE, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, ast_log(), and LOG_DEBUG.

Referenced by dahdi_hangup().

06028 {
06029    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06030    switch (cause) {
06031    case AST_CAUSE_USER_BUSY:
06032    case AST_CAUSE_CALL_REJECTED:
06033    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06034       r2cause = OR2_CAUSE_BUSY_NUMBER;
06035       break;
06036 
06037    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06038    case AST_CAUSE_SWITCH_CONGESTION:
06039       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06040       break;
06041 
06042    case AST_CAUSE_UNALLOCATED:
06043       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06044       break;
06045 
06046    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06047    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06048       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06049       break;
06050 
06051    case AST_CAUSE_NO_ANSWER:
06052    case AST_CAUSE_NO_USER_RESPONSE:
06053       r2cause = OR2_CAUSE_NO_ANSWER;
06054       break;
06055 
06056    default:
06057       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06058       break;
06059    }
06060    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06061          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06062    return r2cause;
06063 }

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 7157 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_lock, ast_mutex_trylock, ast_mutex_unlock, ast_read(), AST_STATE_RINGING, ast_verb, ast_waitfor_n(), ast_write(), sig_pri_chan::call, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index, dahdi_link(), dahdi_sig_pri_lib_handles(), dahdi_unlink(), dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), f, ast_channel::fds, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, sig_pri_span::lock, dahdi_pvt::lock, LOG_NOTICE, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::pulsedial, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, subnames, dahdi_pvt::subs, t1, ast_channel::tech_pvt, sig_pri_span::transfer, and update_conf().

07158 {
07159    struct ast_channel *who;
07160    struct dahdi_pvt *p0, *p1, *op0, *op1;
07161    struct dahdi_pvt *master = NULL, *slave = NULL;
07162    struct ast_frame *f;
07163    int inconf = 0;
07164    int nothingok = 1;
07165    int ofd0, ofd1;
07166    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07167    int os0 = -1, os1 = -1;
07168    int priority = 0;
07169    struct ast_channel *oc0, *oc1;
07170    enum ast_bridge_result res;
07171 #ifdef PRI_2BCT
07172    int triedtopribridge = 0;
07173    q931_call *q931c0;
07174    q931_call *q931c1;
07175 #endif
07176 
07177    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07178       There is code below to handle it properly until DTMF is actually seen,
07179       but due to currently unresolved issues it's ignored...
07180    */
07181 
07182    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07183       return AST_BRIDGE_FAILED_NOWARN;
07184 
07185    ast_channel_lock(c0);
07186    while (ast_channel_trylock(c1)) {
07187       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07188    }
07189 
07190    p0 = c0->tech_pvt;
07191    p1 = c1->tech_pvt;
07192    /* cant do pseudo-channels here */
07193    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07194       ast_channel_unlock(c0);
07195       ast_channel_unlock(c1);
07196       return AST_BRIDGE_FAILED_NOWARN;
07197    }
07198 
07199    oi0 = dahdi_get_index(c0, p0, 0);
07200    oi1 = dahdi_get_index(c1, p1, 0);
07201    if ((oi0 < 0) || (oi1 < 0)) {
07202       ast_channel_unlock(c0);
07203       ast_channel_unlock(c1);
07204       return AST_BRIDGE_FAILED;
07205    }
07206 
07207    op0 = p0 = c0->tech_pvt;
07208    op1 = p1 = c1->tech_pvt;
07209    ofd0 = c0->fds[0];
07210    ofd1 = c1->fds[0];
07211    oc0 = p0->owner;
07212    oc1 = p1->owner;
07213 
07214    if (ast_mutex_trylock(&p0->lock)) {
07215       /* Don't block, due to potential for deadlock */
07216       ast_channel_unlock(c0);
07217       ast_channel_unlock(c1);
07218       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07219       return AST_BRIDGE_RETRY;
07220    }
07221    if (ast_mutex_trylock(&p1->lock)) {
07222       /* Don't block, due to potential for deadlock */
07223       ast_mutex_unlock(&p0->lock);
07224       ast_channel_unlock(c0);
07225       ast_channel_unlock(c1);
07226       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07227       return AST_BRIDGE_RETRY;
07228    }
07229 
07230    if ((p0->callwaiting && p0->callwaitingcallerid)
07231       || (p1->callwaiting && p1->callwaitingcallerid)) {
07232       /*
07233        * Call Waiting Caller ID requires DTMF detection to know if it
07234        * can send the CID spill.
07235        *
07236        * For now, don't attempt to native bridge if either channel
07237        * needs DTMF detection.  There is code below to handle it
07238        * properly until DTMF is actually seen, but due to currently
07239        * unresolved issues it's ignored...
07240        */
07241       ast_mutex_unlock(&p0->lock);
07242       ast_mutex_unlock(&p1->lock);
07243       ast_channel_unlock(c0);
07244       ast_channel_unlock(c1);
07245       return AST_BRIDGE_FAILED_NOWARN;
07246    }
07247 
07248 #if defined(HAVE_PRI)
07249    if ((dahdi_sig_pri_lib_handles(p0->sig)
07250          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07251       || (dahdi_sig_pri_lib_handles(p1->sig)
07252          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07253       /*
07254        * PRI nobch channels (hold and call waiting) are equivalent to
07255        * pseudo channels and cannot be done here.
07256        */
07257       ast_mutex_unlock(&p0->lock);
07258       ast_mutex_unlock(&p1->lock);
07259       ast_channel_unlock(c0);
07260       ast_channel_unlock(c1);
07261       return AST_BRIDGE_FAILED_NOWARN;
07262    }
07263 #endif   /* defined(HAVE_PRI) */
07264 
07265    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07266       if (p0->owner && p1->owner) {
07267          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07268          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07269             master = p0;
07270             slave = p1;
07271             inconf = 1;
07272          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07273             master = p1;
07274             slave = p0;
07275             inconf = 1;
07276          } else {
07277             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07278             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07279                p0->channel,
07280                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07281                p0->subs[SUB_REAL].inthreeway, p0->channel,
07282                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07283                p1->subs[SUB_REAL].inthreeway);
07284          }
07285          nothingok = 0;
07286       }
07287    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07288       if (p1->subs[SUB_THREEWAY].inthreeway) {
07289          master = p1;
07290          slave = p0;
07291          nothingok = 0;
07292       }
07293    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07294       if (p0->subs[SUB_THREEWAY].inthreeway) {
07295          master = p0;
07296          slave = p1;
07297          nothingok = 0;
07298       }
07299    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07300       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07301          don't put us in anything */
07302       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07303          master = p1;
07304          slave = p0;
07305          nothingok = 0;
07306       }
07307    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07308       /* Same as previous */
07309       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07310          master = p0;
07311          slave = p1;
07312          nothingok = 0;
07313       }
07314    }
07315    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07316       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07317    if (master && slave) {
07318       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07319          in an active threeway call with a channel that is ringing, we should
07320          indicate ringing. */
07321       if ((oi1 == SUB_THREEWAY) &&
07322          p1->subs[SUB_THREEWAY].inthreeway &&
07323          p1->subs[SUB_REAL].owner &&
07324          p1->subs[SUB_REAL].inthreeway &&
07325          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07326          ast_debug(1,
07327             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07328             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07329          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07330          os1 = p1->subs[SUB_REAL].owner->_state;
07331       } else {
07332          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07333             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07334          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07335       }
07336       if ((oi0 == SUB_THREEWAY) &&
07337          p0->subs[SUB_THREEWAY].inthreeway &&
07338          p0->subs[SUB_REAL].owner &&
07339          p0->subs[SUB_REAL].inthreeway &&
07340          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07341          ast_debug(1,
07342             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07343             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07344          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07345          os0 = p0->subs[SUB_REAL].owner->_state;
07346       } else {
07347          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07348             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07349          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07350       }
07351       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07352          if (!p0->echocanbridged || !p1->echocanbridged) {
07353             /* Disable echo cancellation if appropriate */
07354             dahdi_disable_ec(p0);
07355             dahdi_disable_ec(p1);
07356          }
07357       }
07358       dahdi_link(slave, master);
07359       master->inconference = inconf;
07360    } else if (!nothingok)
07361       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07362 
07363    update_conf(p0);
07364    update_conf(p1);
07365    t0 = p0->subs[SUB_REAL].inthreeway;
07366    t1 = p1->subs[SUB_REAL].inthreeway;
07367 
07368    ast_mutex_unlock(&p0->lock);
07369    ast_mutex_unlock(&p1->lock);
07370 
07371    ast_channel_unlock(c0);
07372    ast_channel_unlock(c1);
07373 
07374    /* Native bridge failed */
07375    if ((!master || !slave) && !nothingok) {
07376       dahdi_enable_ec(p0);
07377       dahdi_enable_ec(p1);
07378       return AST_BRIDGE_FAILED;
07379    }
07380 
07381    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07382 
07383    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07384       disable_dtmf_detect(op0);
07385 
07386    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07387       disable_dtmf_detect(op1);
07388 
07389    for (;;) {
07390       struct ast_channel *c0_priority[2] = {c0, c1};
07391       struct ast_channel *c1_priority[2] = {c1, c0};
07392 
07393       /* Here's our main loop...  Start by locking things, looking for private parts,
07394          and then balking if anything is wrong */
07395 
07396       ast_channel_lock(c0);
07397       while (ast_channel_trylock(c1)) {
07398          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07399       }
07400 
07401       p0 = c0->tech_pvt;
07402       p1 = c1->tech_pvt;
07403 
07404       if (op0 == p0)
07405          i0 = dahdi_get_index(c0, p0, 1);
07406       if (op1 == p1)
07407          i1 = dahdi_get_index(c1, p1, 1);
07408 
07409       ast_channel_unlock(c0);
07410       ast_channel_unlock(c1);
07411 
07412       if (!timeoutms ||
07413          (op0 != p0) ||
07414          (op1 != p1) ||
07415          (ofd0 != c0->fds[0]) ||
07416          (ofd1 != c1->fds[0]) ||
07417          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07418          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07419          (oc0 != p0->owner) ||
07420          (oc1 != p1->owner) ||
07421          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07422          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07423          (oi0 != i0) ||
07424          (oi1 != i1)) {
07425          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07426             op0->channel, oi0, op1->channel, oi1);
07427          res = AST_BRIDGE_RETRY;
07428          goto return_from_bridge;
07429       }
07430 
07431 #ifdef PRI_2BCT
07432       if (!triedtopribridge) {
07433          triedtopribridge = 1;
07434          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07435             ast_mutex_lock(&p0->pri->lock);
07436             switch (p0->sig) {
07437             case SIG_PRI_LIB_HANDLE_CASES:
07438                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07439                break;
07440             default:
07441                q931c0 = NULL;
07442                break;
07443             }
07444             switch (p1->sig) {
07445             case SIG_PRI_LIB_HANDLE_CASES:
07446                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07447                break;
07448             default:
07449                q931c1 = NULL;
07450                break;
07451             }
07452             if (q931c0 && q931c1) {
07453                pri_channel_bridge(q931c0, q931c1);
07454             }
07455             ast_mutex_unlock(&p0->pri->lock);
07456          }
07457       }
07458 #endif
07459 
07460       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07461       if (!who) {
07462          ast_debug(1, "Ooh, empty read...\n");
07463          continue;
07464       }
07465       f = ast_read(who);
07466       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07467          *fo = f;
07468          *rc = who;
07469          res = AST_BRIDGE_COMPLETE;
07470          goto return_from_bridge;
07471       }
07472       if (f->frametype == AST_FRAME_DTMF) {
07473          if ((who == c0) && p0->pulsedial) {
07474             ast_write(c1, f);
07475          } else if ((who == c1) && p1->pulsedial) {
07476             ast_write(c0, f);
07477          } else {
07478             *fo = f;
07479             *rc = who;
07480             res = AST_BRIDGE_COMPLETE;
07481             goto return_from_bridge;
07482          }
07483       }
07484       ast_frfree(f);
07485 
07486       /* Swap who gets priority */
07487       priority = !priority;
07488    }
07489 
07490 return_from_bridge:
07491    if (op0 == p0)
07492       dahdi_enable_ec(p0);
07493 
07494    if (op1 == p1)
07495       dahdi_enable_ec(p1);
07496 
07497    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07498       enable_dtmf_detect(op0);
07499 
07500    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07501       enable_dtmf_detect(op1);
07502 
07503    dahdi_unlink(slave, master, 1);
07504 
07505    return res;
07506 }

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

Definition at line 5303 of file chan_dahdi.c.

References ast_channel::_state, analog_call(), analog_lib_handles(), ast_copy_string(), ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_UP, dahdi_pvt::callwaitrings, dahdi_pvt::channel, ast_channel::connected, dahdi_r2_get_channel_category(), dahdi_sig_pri_lib_handles(), dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, errno, dahdi_pvt::hidecallerid, ast_party_connected_line::id, IS_DIGITAL, dahdi_pvt::law, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_progress, ast_channel::name, dahdi_subchannel::needbusy, ast_party_id::number, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_gain(), dahdi_pvt::sig, SIG_MFCR2, sig_pri_call(), dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_call(), ast_party_number::str, dahdi_pvt::stripmsd, SUB_REAL, dahdi_pvt::subs, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pvt::txdrc, dahdi_pvt::txgain, ast_party_number::valid, and dahdi_pvt::waitingfordt.

05304 {
05305    struct dahdi_pvt *p = ast->tech_pvt;
05306    int x, res, mysig;
05307    char dest[256]; /* must be same length as p->dialdest */
05308 
05309    ast_mutex_lock(&p->lock);
05310    ast_copy_string(dest, rdest, sizeof(dest));
05311    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05312    if ((ast->_state == AST_STATE_BUSY)) {
05313       p->subs[SUB_REAL].needbusy = 1;
05314       ast_mutex_unlock(&p->lock);
05315       return 0;
05316    }
05317    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05318       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05319       ast_mutex_unlock(&p->lock);
05320       return -1;
05321    }
05322    p->waitingfordt.tv_sec = 0;
05323    p->dialednone = 0;
05324    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05325    {
05326       /* Special pseudo -- automatically up */
05327       ast_setstate(ast, AST_STATE_UP);
05328       ast_mutex_unlock(&p->lock);
05329       return 0;
05330    }
05331    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05332    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05333    if (res)
05334       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05335    p->outgoing = 1;
05336 
05337    if (IS_DIGITAL(ast->transfercapability)){
05338       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05339    } else {
05340       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05341    }  
05342 
05343 #ifdef HAVE_PRI
05344    if (dahdi_sig_pri_lib_handles(p->sig)) {
05345       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05346          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05347       ast_mutex_unlock(&p->lock);
05348       return res;
05349    }
05350 #endif
05351 
05352 #if defined(HAVE_SS7)
05353    if (p->sig == SIG_SS7) {
05354       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05355       ast_mutex_unlock(&p->lock);
05356       return res;
05357    }
05358 #endif   /* defined(HAVE_SS7) */
05359 
05360    /* If this is analog signalling we can exit here */
05361    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05362       p->callwaitrings = 0;
05363       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05364       ast_mutex_unlock(&p->lock);
05365       return res;
05366    }
05367 
05368    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05369    switch (mysig) {
05370    case 0:
05371       /* Special pseudo -- automatically up*/
05372       ast_setstate(ast, AST_STATE_UP);
05373       break;
05374    case SIG_MFCR2:
05375       break;
05376    default:
05377       ast_debug(1, "not yet implemented\n");
05378       ast_mutex_unlock(&p->lock);
05379       return -1;
05380    }
05381 
05382 #ifdef HAVE_OPENR2
05383    if (p->mfcr2) {
05384       openr2_calling_party_category_t chancat;
05385       int callres = 0;
05386       char *c, *l;
05387 
05388       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05389       p->dialdest[0] = '\0';
05390 
05391       c = strchr(dest, '/');
05392       if (c) {
05393          c++;
05394       } else {
05395          c = "";
05396       }
05397       if (!p->hidecallerid) {
05398          l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05399       } else {
05400          l = NULL;
05401       }
05402       if (strlen(c) < p->stripmsd) {
05403          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05404          ast_mutex_unlock(&p->lock);
05405          return -1;
05406       }
05407       p->dialing = 1;
05408       chancat = dahdi_r2_get_channel_category(ast);
05409       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05410       if (-1 == callres) {
05411          ast_mutex_unlock(&p->lock);
05412          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05413          return -1;
05414       }
05415       p->mfcr2_call_accepted = 0;
05416       p->mfcr2_progress = 0;
05417       ast_setstate(ast, AST_STATE_DIALING);
05418    }
05419 #endif /* HAVE_OPENR2 */
05420    ast_mutex_unlock(&p->lock);
05421    return 0;
05422 }

static int dahdi_callwait ( struct ast_channel ast  )  [static]

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

05271 {
05272    struct dahdi_pvt *p = ast->tech_pvt;
05273    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05274    if (p->cidspill) {
05275       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05276       ast_free(p->cidspill);
05277    }
05278 
05279    /*
05280     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05281     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05282     */
05283    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05284       return -1;
05285    save_conference(p);
05286    /* Silence */
05287    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05288    if (!p->callwaitrings && p->callwaitingcallerid) {
05289       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05290       p->callwaitcas = 1;
05291       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05292    } else {
05293       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05294       p->callwaitcas = 0;
05295       p->cidlen = 2400 + READ_SIZE * 4;
05296    }
05297    p->cidpos = 0;
05298    send_callerid(p);
05299 
05300    return 0;
05301 }

static int dahdi_cc_callback ( struct ast_channel inbound,
const char *  dest,
ast_cc_callback_fn  callback 
) [static]

Callback made when dial failed to get a channel out of dahdi_request().

Since:
1.8
Parameters:
inbound Incoming asterisk channel.
dest Same dial string passed to dahdi_request().
callback Callback into CC core to announce a busy channel available for CC.
This callback acts like a forked dial with all prongs of the fork busy. Essentially, for each channel that could have taken the call, indicate that it is busy.

Return values:
0 on success.
-1 on error.

Definition at line 13749 of file chan_dahdi.c.

References AST_CC_GENERIC_MONITOR_TYPE, AST_CC_MONITOR_ALWAYS, AST_CC_MONITOR_GENERIC, AST_CC_MONITOR_NATIVE, AST_CC_MONITOR_NEVER, AST_CHANNEL_NAME, ast_free, ast_get_cc_monitor_policy(), ast_mutex_lock, ast_mutex_unlock, ast_str_buffer(), dahdi_pvt::cc_params, sig_pri_span::cc_params, dahdi_starting_point::channelmatch, create_channel_name(), dahdi_sig_pri_lib_handles(), determine_starting_point(), dahdi_starting_point::groupmatch, iflock, is_group_or_channel_match(), dahdi_pvt::pri, and dahdi_starting_point::span.

13750 {
13751    struct dahdi_pvt *p;
13752    struct dahdi_pvt *exitpvt;
13753    struct dahdi_starting_point start;
13754    int groupmatched = 0;
13755    int channelmatched = 0;
13756 
13757    ast_mutex_lock(&iflock);
13758    p = determine_starting_point(dest, &start);
13759    if (!p) {
13760       ast_mutex_unlock(&iflock);
13761       return -1;
13762    }
13763    exitpvt = p;
13764    for (;;) {
13765       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13766          /* We found a potential match. call the callback */
13767          struct ast_str *device_name;
13768          char *dash;
13769          const char *monitor_type;
13770          char dialstring[AST_CHANNEL_NAME];
13771          char full_device_name[AST_CHANNEL_NAME];
13772 
13773          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13774          case AST_CC_MONITOR_NEVER:
13775             break;
13776          case AST_CC_MONITOR_NATIVE:
13777          case AST_CC_MONITOR_ALWAYS:
13778          case AST_CC_MONITOR_GENERIC:
13779 #if defined(HAVE_PRI)
13780             if (dahdi_sig_pri_lib_handles(p->sig)) {
13781                /*
13782                 * ISDN is in a trunk busy condition so we need to monitor
13783                 * the span congestion device state.
13784                 */
13785                snprintf(full_device_name, sizeof(full_device_name),
13786                   "DAHDI/I%d/congestion", p->pri->span);
13787             } else
13788 #endif   /* defined(HAVE_PRI) */
13789             {
13790 #if defined(HAVE_PRI)
13791                device_name = create_channel_name(p, 1, "");
13792 #else
13793                device_name = create_channel_name(p);
13794 #endif   /* defined(HAVE_PRI) */
13795                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13796                   device_name ? ast_str_buffer(device_name) : "");
13797                ast_free(device_name);
13798                /*
13799                 * The portion after the '-' in the channel name is either a random
13800                 * number, a sequence number, or a subchannel number. None are
13801                 * necessary so strip them off.
13802                 */
13803                dash = strrchr(full_device_name, '-');
13804                if (dash) {
13805                   *dash = '\0';
13806                }
13807             }
13808             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13809 
13810             /*
13811              * Analog can only do generic monitoring.
13812              * ISDN is in a trunk busy condition and any "device" is going
13813              * to be busy until a B channel becomes available.  The generic
13814              * monitor can do this task.
13815              */
13816             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13817             callback(inbound,
13818 #if defined(HAVE_PRI)
13819                p->pri ? p->pri->cc_params : p->cc_params,
13820 #else
13821                p->cc_params,
13822 #endif   /* defined(HAVE_PRI) */
13823                monitor_type, full_device_name, dialstring, NULL);
13824             break;
13825          }
13826       }
13827       p = start.backwards ? p->prev : p->next;
13828       if (!p) {
13829          p = start.backwards ? ifend : iflist;
13830       }
13831       if (p == exitpvt) {
13832          break;
13833       }
13834    }
13835    ast_mutex_unlock(&iflock);
13836    return 0;
13837 }

static struct dahdi_chan_conf dahdi_chan_conf_default ( void   )  [static]

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

Definition at line 1363 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

01364 {
01365    /* recall that if a field is not included here it is initialized
01366     * to 0 or equivalent
01367     */
01368    struct dahdi_chan_conf conf = {
01369 #ifdef HAVE_PRI
01370       .pri.pri = {
01371          .nsf = PRI_NSF_NONE,
01372          .switchtype = PRI_SWITCH_NI2,
01373          .dialplan = PRI_UNKNOWN + 1,
01374          .localdialplan = PRI_NATIONAL_ISDN + 1,
01375          .nodetype = PRI_CPE,
01376          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01377 
01378 #if defined(HAVE_PRI_CCSS)
01379          .cc_ptmp_recall_mode = 1,/* specificRecall */
01380          .cc_qsig_signaling_link_req = 1,/* retain */
01381          .cc_qsig_signaling_link_rsp = 1,/* retain */
01382 #endif   /* defined(HAVE_PRI_CCSS) */
01383 
01384          .minunused = 2,
01385          .idleext = "",
01386          .idledial = "",
01387          .internationalprefix = "",
01388          .nationalprefix = "",
01389          .localprefix = "",
01390          .privateprefix = "",
01391          .unknownprefix = "",
01392          .resetinterval = -1,
01393       },
01394 #endif
01395 #if defined(HAVE_SS7)
01396       .ss7.ss7 = {
01397          .called_nai = SS7_NAI_NATIONAL,
01398          .calling_nai = SS7_NAI_NATIONAL,
01399          .internationalprefix = "",
01400          .nationalprefix = "",
01401          .subscriberprefix = "",
01402          .unknownprefix = ""
01403       },
01404 #endif   /* defined(HAVE_SS7) */
01405 #ifdef HAVE_OPENR2
01406       .mfcr2 = {
01407          .variant = OR2_VAR_ITU,
01408          .mfback_timeout = -1,
01409          .metering_pulse_timeout = -1,
01410          .max_ani = 10,
01411          .max_dnis = 4,
01412          .get_ani_first = -1,
01413 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01414          .skip_category_request = -1,
01415 #endif
01416          .call_files = 0,
01417          .allow_collect_calls = 0,
01418          .charge_calls = 1,
01419          .accept_on_offer = 1,
01420          .forced_release = 0,
01421          .double_answer = 0,
01422          .immediate_accept = -1,
01423          .logdir = "",
01424          .r2proto_file = "",
01425          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01426          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01427       },
01428 #endif
01429       .chan = {
01430          .context = "default",
01431          .cid_num = "",
01432          .cid_name = "",
01433          .cid_tag = "",
01434          .mohinterpret = "default",
01435          .mohsuggest = "",
01436          .parkinglot = "",
01437          .transfertobusy = 1,
01438 
01439          .cid_signalling = CID_SIG_BELL,
01440          .cid_start = CID_START_RING,
01441          .dahditrcallerid = 0,
01442          .use_callerid = 1,
01443          .sig = -1,
01444          .outsigmod = -1,
01445 
01446          .cid_rxgain = +5.0,
01447 
01448          .tonezone = -1,
01449 
01450          .echocancel.head.tap_length = 1,
01451 
01452          .busycount = 3,
01453          .busycompare = 0,
01454          .busytonelength = 0,
01455          .busyquietlength = 0,
01456          .busyfuzziness = 0,
01457          .silencethreshold = 0,
01458 
01459          .accountcode = "",
01460 
01461          .mailbox = "",
01462 
01463 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01464          .mwisend_fsk = 1,
01465 #endif
01466          .polarityonanswerdelay = 600,
01467 
01468          .sendcalleridafter = DEFAULT_CIDRINGS,
01469 
01470          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01471          .buf_no = numbufs,
01472          .usefaxbuffers = 0,
01473          .cc_params = ast_cc_config_params_init(),
01474       },
01475       .timing = {
01476          .prewinktime = -1,
01477          .preflashtime = -1,
01478          .winktime = -1,
01479          .flashtime = -1,
01480          .starttime = -1,
01481          .rxwinktime = -1,
01482          .rxflashtime = -1,
01483          .debouncetime = -1
01484       },
01485       .is_sig_auto = 1,
01486       .smdi_port = "/dev/ttyS0",
01487    };
01488 
01489    return conf;
01490 }

static int dahdi_channels_data_provider_get ( const struct ast_data_search search,
struct ast_data data_root 
) [static]

Definition at line 18351 of file chan_dahdi.c.

References ast_data_add_node(), ast_data_add_structure, ast_data_remove_node(), ast_data_search_match(), ast_mutex_lock, ast_mutex_unlock, iflist, and dahdi_pvt::next.

18353 {
18354    struct dahdi_pvt *tmp;
18355    struct ast_data *data_channel;
18356 
18357    ast_mutex_lock(&iflock);
18358    for (tmp = iflist; tmp; tmp = tmp->next) {
18359       data_channel = ast_data_add_node(data_root, "channel");
18360       if (!data_channel) {
18361          continue;
18362       }
18363 
18364       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18365 
18366       /* if this channel doesn't match remove it. */
18367       if (!ast_data_search_match(search, data_channel)) {
18368          ast_data_remove_node(data_root, data_channel);
18369       }
18370    }
18371    ast_mutex_unlock(&iflock);
18372 
18373    return 0;
18374 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 4297 of file chan_dahdi.c.

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

04298 {
04299    if (fd > 0)
04300       close(fd);
04301 }

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

Definition at line 4310 of file chan_dahdi.c.

References dahdi_close(), sig_pri_span::fds, and dahdi_pri::pri.

Referenced by __unload_module(), and prepare_pri().

04311 {
04312    dahdi_close(pri->pri.fds[fd_num]);
04313    pri->pri.fds[fd_num] = -1;
04314 }

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

Definition at line 4318 of file chan_dahdi.c.

References dahdi_close(), sig_ss7_linkset::fds, and dahdi_ss7::ss7.

Referenced by __unload_module(), and linkset_addsigchan().

04319 {
04320    dahdi_close(ss7->ss7.fds[fd_num]);
04321    ss7->ss7.fds[fd_num] = -1;
04322 }

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

Definition at line 4303 of file chan_dahdi.c.

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

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

04304 {
04305    dahdi_close(chan_pvt->subs[sub_num].dfd);
04306    chan_pvt->subs[sub_num].dfd = -1;
04307 }

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

Definition at line 5113 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, errno, LOG_WARNING, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_handle_dtmf(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_read(), my_confmute(), and my_handle_dtmf().

05114 {
05115    int x, res;
05116 
05117    x = muted;
05118 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05119    switch (p->sig) {
05120 #if defined(HAVE_PRI)
05121    case SIG_PRI_LIB_HANDLE_CASES:
05122       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05123          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05124          break;
05125       }
05126       /* Fall through */
05127 #endif   /* defined(HAVE_PRI) */
05128 #if defined(HAVE_SS7)
05129    case SIG_SS7:
05130 #endif   /* defined(HAVE_SS7) */
05131       {
05132          int y = 1;
05133 
05134          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05135          if (res)
05136             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05137                p->channel, strerror(errno));
05138       }
05139       break;
05140    default:
05141       break;
05142    }
05143 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05144    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05145    if (res < 0)
05146       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05147    return res;
05148 }

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

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

14902 {
14903    int channel;
14904    int ret;
14905    switch (cmd) {
14906    case CLI_INIT:
14907       e->command = "dahdi destroy channel";
14908       e->usage =
14909          "Usage: dahdi destroy channel <chan num>\n"
14910          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
14911       return NULL;
14912    case CLI_GENERATE:
14913       return NULL;
14914    }
14915    if (a->argc != 4)
14916       return CLI_SHOWUSAGE;
14917 
14918    channel = atoi(a->argv[3]);
14919    ret = dahdi_destroy_channel_bynum(channel);
14920    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14921 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

Definition at line 11289 of file chan_dahdi.c.

References ast_module_unref(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, destroy_channel(), iflist, iflock, dahdi_pvt::next, RESULT_SUCCESS, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_destroy_channel().

11290 {
11291    struct dahdi_pvt *cur;
11292 
11293    ast_mutex_lock(&iflock);
11294    for (cur = iflist; cur; cur = cur->next) {
11295       if (cur->channel == channel) {
11296          int x = DAHDI_FLASH;
11297 
11298          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11299          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11300 
11301          destroy_channel(cur, 1);
11302          ast_mutex_unlock(&iflock);
11303          ast_module_unref(ast_module_info->self);
11304          return RESULT_SUCCESS;
11305       }
11306    }
11307    ast_mutex_unlock(&iflock);
11308    return RESULT_FAILURE;
11309 }

static int dahdi_devicestate ( void *  data  )  [static]

Definition at line 13687 of file chan_dahdi.c.

References AST_DEVICE_UNKNOWN, sig_pri_span::congestion_devstate, dahdi_pri::pri, and pris.

13688 {
13689 #if defined(HAVE_PRI)
13690    char *device;
13691    unsigned span;
13692    int res;
13693 
13694    device = data;
13695 
13696    if (*device != 'I') {
13697       /* The request is not for an ISDN span device. */
13698       return AST_DEVICE_UNKNOWN;
13699    }
13700    res = sscanf(device, "I%30u", &span);
13701    if (res != 1 || !span || NUM_SPANS < span) {
13702       /* Bad format for ISDN span device name. */
13703       return AST_DEVICE_UNKNOWN;
13704    }
13705    device = strchr(device, '/');
13706    if (!device) {
13707       /* Bad format for ISDN span device name. */
13708       return AST_DEVICE_UNKNOWN;
13709    }
13710 
13711    /*
13712     * Since there are currently no other span devstate's defined,
13713     * it must be congestion.
13714     */
13715 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13716    ++device;
13717    if (!strcmp(device, "congestion"))
13718 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13719    {
13720       return pris[span - 1].pri.congestion_devstate;
13721    }
13722 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13723    else if (!strcmp(device, "threshold")) {
13724       return pris[span - 1].pri.threshold_devstate;
13725    }
13726    return AST_DEVICE_UNKNOWN;
13727 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13728 #else
13729    return AST_DEVICE_UNKNOWN;
13730 #endif   /* defined(HAVE_PRI) */
13731 }

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

Definition at line 4401 of file chan_dahdi.c.

References ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::begindigit, dahdi_get_index, dahdi_pvt::dialing, digit_to_dtmfindex(), errno, dahdi_pvt::lock, LOG_WARNING, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, sig_pri_digit_begin(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

04402 {
04403    struct dahdi_pvt *pvt;
04404    int idx;
04405    int dtmf = -1;
04406    int res;
04407 
04408    pvt = chan->tech_pvt;
04409 
04410    ast_mutex_lock(&pvt->lock);
04411 
04412    idx = dahdi_get_index(chan, pvt, 0);
04413 
04414    if ((idx != SUB_REAL) || !pvt->owner)
04415       goto out;
04416 
04417 #ifdef HAVE_PRI
04418    switch (pvt->sig) {
04419    case SIG_PRI_LIB_HANDLE_CASES:
04420       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04421       if (!res)
04422          goto out;
04423       break;
04424    default:
04425       break;
04426    }
04427 #endif
04428    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04429       goto out;
04430 
04431    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04432       struct dahdi_dialoperation zo = {
04433          .op = DAHDI_DIAL_OP_APPEND,
04434       };
04435 
04436       zo.dialstr[0] = 'T';
04437       zo.dialstr[1] = digit;
04438       zo.dialstr[2] = '\0';
04439       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04440          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
04441       else
04442          pvt->dialing = 1;
04443    } else {
04444       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
04445       pvt->dialing = 1;
04446       pvt->begindigit = digit;
04447    }
04448 
04449 out:
04450    ast_mutex_unlock(&pvt->lock);
04451 
04452    return 0;
04453 }

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

Definition at line 4455 of file chan_dahdi.c.

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

04456 {
04457    struct dahdi_pvt *pvt;
04458    int res = 0;
04459    int idx;
04460    int x;
04461 
04462    pvt = chan->tech_pvt;
04463 
04464    ast_mutex_lock(&pvt->lock);
04465 
04466    idx = dahdi_get_index(chan, pvt, 0);
04467 
04468    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04469       goto out;
04470 
04471 #ifdef HAVE_PRI
04472    /* This means that the digit was already sent via PRI signalling */
04473    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04474       goto out;
04475    }
04476 #endif
04477 
04478    if (pvt->begindigit) {
04479       x = -1;
04480       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
04481       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04482       pvt->dialing = 0;
04483       pvt->begindigit = 0;
04484    }
04485 
04486 out:
04487    ast_mutex_unlock(&pvt->lock);
04488 
04489    return res;
04490 }

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 4905 of file chan_dahdi.c.

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

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

04906 {
04907    int res;
04908 
04909    if (p->echocanon) {
04910       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04911 
04912       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04913 
04914       if (res)
04915          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04916       else
04917          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04918    }
04919 
04920    p->echocanon = 0;
04921 }

static int dahdi_dnd ( struct dahdi_pvt dahdichan,
int  flag 
) [static]

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

Parameters:
dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
flag on 1 to enable, 0 to disable, -1 return dnd value
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 9751 of file chan_dahdi.c.

References analog_dnd(), analog_lib_handles(), ast_verb, dahdi_pvt::channel, dahdi_pvt::dnd, EVENT_FLAG_SYSTEM, manager_event, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, and dahdi_pvt::sig_pvt.

Referenced by action_dahdidndoff(), action_dahdidndon(), action_dahdishowchannels(), analog_ss_thread(), dahdi_set_dnd(), and dahdi_show_channel().

09752 {
09753    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09754       return analog_dnd(dahdichan->sig_pvt, flag);
09755    }
09756 
09757    if (flag == -1) {
09758       return dahdichan->dnd;
09759    }
09760 
09761    /* Do not disturb */
09762    dahdichan->dnd = flag;
09763    ast_verb(3, "%s DND on channel %d\n",
09764          flag? "Enabled" : "Disabled",
09765          dahdichan->channel);
09766    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09767          "Channel: DAHDI/%d\r\n"
09768          "Status: %s\r\n", dahdichan->channel,
09769          flag? "enabled" : "disabled");
09770 
09771    return 0;
09772 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 4833 of file chan_dahdi.c.

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

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_bridge(), dahdi_func_write(), dahdi_handle_event(), dahdi_r2_on_call_accepted(), dahdi_setoption(), handle_init_event(), and my_set_echocanceller().

04834 {
04835    int res;
04836    if (!p)
04837       return;
04838    if (p->echocanon) {
04839       ast_debug(1, "Echo cancellation already on\n");
04840       return;
04841    }
04842    if (p->digital) {
04843       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04844       return;
04845    }
04846    if (p->echocancel.head.tap_length) {
04847 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04848       switch (p->sig) {
04849 #if defined(HAVE_PRI)
04850       case SIG_PRI_LIB_HANDLE_CASES:
04851          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04852             /*
04853              * PRI nobch pseudo channel.  Does not need ec anyway.
04854              * Does not handle ioctl(DAHDI_AUDIOMODE)
04855              */
04856             return;
04857          }
04858          /* Fall through */
04859 #endif   /* defined(HAVE_PRI) */
04860 #if defined(HAVE_SS7)
04861       case SIG_SS7:
04862 #endif   /* defined(HAVE_SS7) */
04863          {
04864             int x = 1;
04865 
04866             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04867             if (res)
04868                ast_log(LOG_WARNING,
04869                   "Unable to enable audio mode on channel %d (%s)\n",
04870                   p->channel, strerror(errno));
04871          }
04872          break;
04873       default:
04874          break;
04875       }
04876 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04877       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04878       if (res) {
04879          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04880       } else {
04881          p->echocanon = 1;
04882          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04883       }
04884    } else
04885       ast_debug(1, "No echo cancellation requested\n");
04886 }

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

Definition at line 8785 of file chan_dahdi.c.

References __dahdi_exception(), analog_exception(), analog_lib_handles(), ast_mutex_lock, ast_mutex_unlock, f, dahdi_pvt::lock, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, dahdi_pvt::sig_pvt, and ast_channel::tech_pvt.

08786 {
08787    struct dahdi_pvt *p = ast->tech_pvt;
08788    struct ast_frame *f;
08789    ast_mutex_lock(&p->lock);
08790    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08791       struct analog_pvt *analog_p = p->sig_pvt;
08792       f = analog_exception(analog_p, ast);
08793    } else {
08794       f = __dahdi_exception(ast);
08795    }
08796    ast_mutex_unlock(&p->lock);
08797    return f;
08798 }

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

Definition at line 15751 of file chan_dahdi.c.

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

Referenced by action_transfer(), and action_transferhangup().

15752 {
15753    if (p) {
15754       switch (mode) {
15755       case TRANSFER:
15756          p->fake_event = DAHDI_EVENT_WINKFLASH;
15757          break;
15758       case HANGUP:
15759          p->fake_event = DAHDI_EVENT_ONHOOK;
15760          break;
15761       default:
15762          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15763       }
15764    }
15765    return 0;
15766 }

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

Definition at line 7508 of file chan_dahdi.c.

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

07509 {
07510    struct dahdi_pvt *p = newchan->tech_pvt;
07511    int x;
07512 
07513    ast_mutex_lock(&p->lock);
07514 
07515    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07516    if (p->owner == oldchan) {
07517       p->owner = newchan;
07518    }
07519    for (x = 0; x < 3; x++) {
07520       if (p->subs[x].owner == oldchan) {
07521          if (!x) {
07522             dahdi_unlink(NULL, p, 0);
07523          }
07524          p->subs[x].owner = newchan;
07525       }
07526    }
07527    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07528       analog_fixup(oldchan, newchan, p->sig_pvt);
07529 #if defined(HAVE_PRI)
07530    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07531       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07532 #endif   /* defined(HAVE_PRI) */
07533 #if defined(HAVE_SS7)
07534    } else if (p->sig == SIG_SS7) {
07535       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07536 #endif   /* defined(HAVE_SS7) */
07537    }
07538    update_conf(p);
07539 
07540    ast_mutex_unlock(&p->lock);
07541 
07542    if (newchan->_state == AST_STATE_RINGING) {
07543       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07544    }
07545    return 0;
07546 }

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

Definition at line 6865 of file chan_dahdi.c.

References ast_copy_string(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, dahdi_pvt::lock, dahdi_pvt::rxgain, dahdi_pvt::sig, SIG_MFCR2, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, dahdi_pvt::span, ast_channel::tech_pvt, and dahdi_pvt::txgain.

06866 {
06867    struct dahdi_pvt *p = chan->tech_pvt;
06868    int res = 0;
06869 
06870    if (!p) {
06871       /* No private structure! */
06872       *buf = '\0';
06873       return -1;
06874    }
06875 
06876    if (!strcasecmp(data, "rxgain")) {
06877       ast_mutex_lock(&p->lock);
06878       snprintf(buf, len, "%f", p->rxgain);
06879       ast_mutex_unlock(&p->lock);
06880    } else if (!strcasecmp(data, "txgain")) {
06881       ast_mutex_lock(&p->lock);
06882       snprintf(buf, len, "%f", p->txgain);
06883       ast_mutex_unlock(&p->lock);
06884    } else if (!strcasecmp(data, "dahdi_channel")) {
06885       ast_mutex_lock(&p->lock);
06886       snprintf(buf, len, "%d", p->channel);
06887       ast_mutex_unlock(&p->lock);
06888    } else if (!strcasecmp(data, "dahdi_span")) {
06889       ast_mutex_lock(&p->lock);
06890       snprintf(buf, len, "%d", p->span);
06891       ast_mutex_unlock(&p->lock);
06892    } else if (!strcasecmp(data, "dahdi_type")) {
06893       ast_mutex_lock(&p->lock);
06894       switch (p->sig) {
06895 #if defined(HAVE_OPENR2)
06896       case SIG_MFCR2:
06897          ast_copy_string(buf, "mfc/r2", len);
06898          break;
06899 #endif   /* defined(HAVE_OPENR2) */
06900 #if defined(HAVE_PRI)
06901       case SIG_PRI_LIB_HANDLE_CASES:
06902          ast_copy_string(buf, "pri", len);
06903          break;
06904 #endif   /* defined(HAVE_PRI) */
06905       case 0:
06906          ast_copy_string(buf, "pseudo", len);
06907          break;
06908 #if defined(HAVE_SS7)
06909       case SIG_SS7:
06910          ast_copy_string(buf, "ss7", len);
06911          break;
06912 #endif   /* defined(HAVE_SS7) */
06913       default:
06914          /* The only thing left is analog ports. */
06915          ast_copy_string(buf, "analog", len);
06916          break;
06917       }
06918       ast_mutex_unlock(&p->lock);
06919 #if defined(HAVE_PRI)
06920 #if defined(HAVE_PRI_REVERSE_CHARGE)
06921    } else if (!strcasecmp(data, "reversecharge")) {
06922       ast_mutex_lock(&p->lock);
06923       switch (p->sig) {
06924       case SIG_PRI_LIB_HANDLE_CASES:
06925          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06926          break;
06927       default:
06928          *buf = '\0';
06929          res = -1;
06930          break;
06931       }
06932       ast_mutex_unlock(&p->lock);
06933 #endif
06934 #if defined(HAVE_PRI_SETUP_KEYPAD)
06935    } else if (!strcasecmp(data, "keypad_digits")) {
06936       ast_mutex_lock(&p->lock);
06937       switch (p->sig) {
06938       case SIG_PRI_LIB_HANDLE_CASES:
06939          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06940             len);
06941          break;
06942       default:
06943          *buf = '\0';
06944          res = -1;
06945          break;
06946       }
06947       ast_mutex_unlock(&p->lock);
06948 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
06949    } else if (!strcasecmp(data, "no_media_path")) {
06950       ast_mutex_lock(&p->lock);
06951       switch (p->sig) {
06952       case SIG_PRI_LIB_HANDLE_CASES:
06953          /*
06954           * TRUE if the call is on hold or is call waiting because
06955           * there is no media path available.
06956           */
06957          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06958          break;
06959       default:
06960          *buf = '\0';
06961          res = -1;
06962          break;
06963       }
06964       ast_mutex_unlock(&p->lock);
06965 #endif   /* defined(HAVE_PRI) */
06966    } else {
06967       *buf = '\0';
06968       res = -1;
06969    }
06970 
06971    return res;
06972 }

static int dahdi_func_write ( struct ast_channel chan,
const char *  function,
char *  data,
const char *  value 
) [static]

Definition at line 7004 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_pvt::echocanon, errno, dahdi_pvt::lock, LOG_WARNING, parse_buffers_policy(), SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

07005 {
07006    struct dahdi_pvt *p = chan->tech_pvt;
07007    int res = 0;
07008 
07009    if (!p) {
07010       /* No private structure! */
07011       return -1;
07012    }
07013 
07014    if (!strcasecmp(data, "buffers")) {
07015       int num_bufs, policy;
07016 
07017       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07018          struct dahdi_bufferinfo bi = {
07019             .txbufpolicy = policy,
07020             .rxbufpolicy = policy,
07021             .bufsize = p->bufsize,
07022             .numbufs = num_bufs,
07023          };
07024          int bpres;
07025 
07026          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07027             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07028          } else {
07029             p->bufferoverrideinuse = 1;
07030          }
07031       } else {
07032          res = -1;
07033       }
07034    } else if (!strcasecmp(data, "echocan_mode")) {
07035       if (!strcasecmp(value, "on")) {
07036          ast_mutex_lock(&p->lock);
07037          dahdi_enable_ec(p);
07038          ast_mutex_unlock(&p->lock);
07039       } else if (!strcasecmp(value, "off")) {
07040          ast_mutex_lock(&p->lock);
07041          dahdi_disable_ec(p);
07042          ast_mutex_unlock(&p->lock);
07043 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07044       } else if (!strcasecmp(value, "fax")) {
07045          int blah = 1;
07046 
07047          ast_mutex_lock(&p->lock);
07048          if (!p->echocanon) {
07049             dahdi_enable_ec(p);
07050          }
07051          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07052             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07053          }
07054          ast_mutex_unlock(&p->lock);
07055       } else if (!strcasecmp(value, "voice")) {
07056          int blah = 0;
07057 
07058          ast_mutex_lock(&p->lock);
07059          if (!p->echocanon) {
07060             dahdi_enable_ec(p);
07061          }
07062          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07063             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07064          }
07065          ast_mutex_unlock(&p->lock);
07066 #endif
07067       } else {
07068          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07069          res = -1;
07070       }
07071    } else {
07072       res = -1;
07073    }
07074 
07075    return res;
07076 }

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 489 of file chan_dahdi.c.

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_handle_event(), mwi_thread(), my_distinctive_ring(), my_get_callerid(), and my_get_event().

00490 {
00491    int j;
00492    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00493       return -1;
00494    return j;
00495 }

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

Definition at line 7685 of file chan_dahdi.c.

References ast_async_goto(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_ANSWER, ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verb, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, ast_channel::caller, dahdi_pvt::callprogress, CALLPROGRESS_FAX, dahdi_pvt::callwaitcas, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, ast_channel::context, dahdi_confmute(), dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, errno, ast_channel::exten, dahdi_subchannel::f, f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxhandled, ast_frame::frametype, ast_party_caller::id, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_NOTICE, ast_channel::macrocontext, ast_channel::name, ast_party_id::number, pbx_builtin_setvar_helper(), S_COR, S_OR, send_cwcidspill(), ast_party_number::str, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, dahdi_pvt::usefaxbuffers, and ast_party_number::valid.

Referenced by dahdi_handle_event(), and dahdi_read().

07686 {
07687    struct dahdi_pvt *p = ast->tech_pvt;
07688    struct ast_frame *f = *dest;
07689 
07690    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07691       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07692       f->subclass.integer, f->subclass.integer, ast->name);
07693 
07694    if (p->confirmanswer) {
07695       if (f->frametype == AST_FRAME_DTMF_END) {
07696          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07697          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07698             of a DTMF digit */
07699          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07700          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07701          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07702          p->confirmanswer = 0;
07703       } else {
07704          p->subs[idx].f.frametype = AST_FRAME_NULL;
07705          p->subs[idx].f.subclass.integer = 0;
07706       }
07707       *dest = &p->subs[idx].f;
07708    } else if (p->callwaitcas) {
07709       if (f->frametype == AST_FRAME_DTMF_END) {
07710          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07711             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07712             ast_free(p->cidspill);
07713             p->cidspill = NULL;
07714             send_cwcidspill(p);
07715          }
07716          p->callwaitcas = 0;
07717       }
07718       p->subs[idx].f.frametype = AST_FRAME_NULL;
07719       p->subs[idx].f.subclass.integer = 0;
07720       *dest = &p->subs[idx].f;
07721    } else if (f->subclass.integer == 'f') {
07722       if (f->frametype == AST_FRAME_DTMF_END) {
07723          /* Fax tone -- Handle and return NULL */
07724          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07725             /* If faxbuffers are configured, use them for the fax transmission */
07726             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07727                struct dahdi_bufferinfo bi = {
07728                   .txbufpolicy = p->faxbuf_policy,
07729                   .bufsize = p->bufsize,
07730                   .numbufs = p->faxbuf_no
07731                };
07732                int res;
07733 
07734                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07735                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07736                } else {
07737                   p->bufferoverrideinuse = 1;
07738                }
07739             }
07740             p->faxhandled = 1;
07741             if (p->dsp) {
07742                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07743                ast_dsp_set_features(p->dsp, p->dsp_features);
07744                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07745             }
07746             if (strcmp(ast->exten, "fax")) {
07747                const char *target_context = S_OR(ast->macrocontext, ast->context);
07748 
07749                /* We need to unlock 'ast' here because ast_exists_extension has the
07750                 * potential to start autoservice on the channel. Such action is prone
07751                 * to deadlock.
07752                 */
07753                ast_mutex_unlock(&p->lock);
07754                ast_channel_unlock(ast);
07755                if (ast_exists_extension(ast, target_context, "fax", 1,
07756                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07757                   ast_channel_lock(ast);
07758                   ast_mutex_lock(&p->lock);
07759                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07760                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07761                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07762                   if (ast_async_goto(ast, target_context, "fax", 1))
07763                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07764                } else {
07765                   ast_channel_lock(ast);
07766                   ast_mutex_lock(&p->lock);
07767                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07768                }
07769             } else {
07770                ast_debug(1, "Already in a fax extension, not redirecting\n");
07771             }
07772          } else {
07773             ast_debug(1, "Fax already handled\n");
07774          }
07775          dahdi_confmute(p, 0);
07776       }
07777       p->subs[idx].f.frametype = AST_FRAME_NULL;
07778       p->subs[idx].f.subclass.integer = 0;
07779       *dest = &p->subs[idx].f;
07780    }
07781 }

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

Definition at line 7804 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), analog_ss_thread(), ast_party_caller::ani, ast_party_caller::ani2, 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_UNHOLD, ast_copy_string(), ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup_with_cause(), ast_setstate(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, attempt_transfer(), ast_channel::caller, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, CANPROGRESSDETECT, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, check_for_conference(), dahdi_pvt::cid_name, cid_name, dahdi_pvt::cid_num, cid_num, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index, dahdi_handle_dtmf(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_ring_phone(), dahdi_set_hook(), dahdi_sig_pri_lib_handles(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, DLA_LOCK, DLA_UNLOCK, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), dahdi_subchannel::f, f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), ast_party_caller::id, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, ast_frame::mallocd, MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, ast_party_id::name, ast_channel::name, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_party_id::number, ast_frame::offset, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, sig_pri_span::overlapdial, dahdi_subchannel::owner, dahdi_pvt::owner, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, sig_pri_span::pri, dahdi_pvt::pri, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_COR, S_OR, ast_frame::samples, save_conference(), dahdi_pvt::sig, sig2str, 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_CALL_LEVEL_PROCEEDING, sig_pri_chan_alarm_notify(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sig_ss7_set_alarm(), ast_frame::src, ast_party_name::str, ast_party_number::str, 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(), ast_party_name::valid, ast_party_number::valid, dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.

Referenced by __dahdi_exception().

07805 {
07806    int res, x;
07807    int idx, mysig;
07808    char *c;
07809    struct dahdi_pvt *p = ast->tech_pvt;
07810    pthread_t threadid;
07811    struct ast_channel *chan;
07812    struct ast_frame *f;
07813 
07814    idx = dahdi_get_index(ast, p, 0);
07815    mysig = p->sig;
07816    if (p->outsigmod > -1)
07817       mysig = p->outsigmod;
07818    p->subs[idx].f.frametype = AST_FRAME_NULL;
07819    p->subs[idx].f.subclass.integer = 0;
07820    p->subs[idx].f.datalen = 0;
07821    p->subs[idx].f.samples = 0;
07822    p->subs[idx].f.mallocd = 0;
07823    p->subs[idx].f.offset = 0;
07824    p->subs[idx].f.src = "dahdi_handle_event";
07825    p->subs[idx].f.data.ptr = NULL;
07826    f = &p->subs[idx].f;
07827 
07828    if (idx < 0)
07829       return &p->subs[idx].f;
07830    if (p->fake_event) {
07831       res = p->fake_event;
07832       p->fake_event = 0;
07833    } else
07834       res = dahdi_get_event(p->subs[idx].dfd);
07835 
07836    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07837 
07838    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07839       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07840       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07841 #if defined(HAVE_PRI)
07842       if (dahdi_sig_pri_lib_handles(p->sig)
07843          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07844          && p->pri
07845          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07846          /* absorb event */
07847       } else
07848 #endif   /* defined(HAVE_PRI) */
07849       {
07850          /* Unmute conference */
07851          dahdi_confmute(p, 0);
07852          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07853          p->subs[idx].f.subclass.integer = res & 0xff;
07854          dahdi_handle_dtmf(ast, idx, &f);
07855       }
07856       return f;
07857    }
07858 
07859    if (res & DAHDI_EVENT_DTMFDOWN) {
07860       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07861 #if defined(HAVE_PRI)
07862       if (dahdi_sig_pri_lib_handles(p->sig)
07863          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07864          && p->pri
07865          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07866          /* absorb event */
07867       } else
07868 #endif   /* defined(HAVE_PRI) */
07869       {
07870          /* Mute conference */
07871          dahdi_confmute(p, 1);
07872          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07873          p->subs[idx].f.subclass.integer = res & 0xff;
07874          dahdi_handle_dtmf(ast, idx, &f);
07875       }
07876       return &p->subs[idx].f;
07877    }
07878 
07879    switch (res) {
07880    case DAHDI_EVENT_EC_DISABLED:
07881       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07882       p->echocanon = 0;
07883       break;
07884 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07885    case DAHDI_EVENT_TX_CED_DETECTED:
07886       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07887       break;
07888    case DAHDI_EVENT_RX_CED_DETECTED:
07889       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07890       break;
07891    case DAHDI_EVENT_EC_NLP_DISABLED:
07892       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07893       break;
07894    case DAHDI_EVENT_EC_NLP_ENABLED:
07895       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07896       break;
07897 #endif
07898    case DAHDI_EVENT_BITSCHANGED:
07899 #ifdef HAVE_OPENR2
07900       if (p->sig != SIG_MFCR2) {
07901          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07902       } else {
07903          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07904          openr2_chan_handle_cas(p->r2chan);
07905       }
07906 #else
07907       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07908 #endif
07909    case DAHDI_EVENT_PULSE_START:
07910       /* Stop tone if there's a pulse start and the PBX isn't started */
07911       if (!ast->pbx)
07912          tone_zone_play_tone(p->subs[idx].dfd, -1);
07913       break;
07914    case DAHDI_EVENT_DIALCOMPLETE:
07915 #ifdef HAVE_OPENR2
07916       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
07917          /* we don't need to do anything for this event for R2 signaling
07918             if the call is being setup */
07919          break;
07920       }
07921 #endif
07922       if (p->inalarm) break;
07923       if ((p->radio || (p->oprmode < 0))) break;
07924       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07925          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
07926          return NULL;
07927       }
07928       if (!x) { /* if not still dialing in driver */
07929          dahdi_enable_ec(p);
07930          if (p->echobreak) {
07931             dahdi_train_ec(p);
07932             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07933             p->dop.op = DAHDI_DIAL_OP_REPLACE;
07934             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07935             p->echobreak = 0;
07936          } else {
07937             p->dialing = 0;
07938             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07939                /* if thru with dialing after offhook */
07940                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
07941                   ast_setstate(ast, AST_STATE_UP);
07942                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07943                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07944                   break;
07945                } else { /* if to state wait for offhook to dial rest */
07946                   /* we now wait for off hook */
07947                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07948                }
07949             }
07950             if (ast->_state == AST_STATE_DIALING) {
07951                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
07952                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
07953                } else if (p->confirmanswer || (!p->dialednone
07954                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
07955                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
07956                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
07957                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
07958                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
07959                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
07960                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
07961                      || (mysig == SIG_SF_FEATB)))) {
07962                   ast_setstate(ast, AST_STATE_RINGING);
07963                } else if (!p->answeronpolarityswitch) {
07964                   ast_setstate(ast, AST_STATE_UP);
07965                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07966                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07967                   /* If aops=0 and hops=1, this is necessary */
07968                   p->polarity = POLARITY_REV;
07969                } else {
07970                   /* Start clean, so we can catch the change to REV polarity when party answers */
07971                   p->polarity = POLARITY_IDLE;
07972                }
07973             }
07974          }
07975       }
07976       break;
07977    case DAHDI_EVENT_ALARM:
07978       switch (p->sig) {
07979 #if defined(HAVE_PRI)
07980       case SIG_PRI_LIB_HANDLE_CASES:
07981          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
07982          break;
07983 #endif   /* defined(HAVE_PRI) */
07984 #if defined(HAVE_SS7)
07985       case SIG_SS7:
07986          sig_ss7_set_alarm(p->sig_pvt, 1);
07987          break;
07988 #endif   /* defined(HAVE_SS7) */
07989       default:
07990          p->inalarm = 1;
07991          break;
07992       }
07993       res = get_alarms(p);
07994       handle_alarms(p, res);
07995 #ifdef HAVE_PRI
07996       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07997          /* fall through intentionally */
07998       } else {
07999          break;
08000       }
08001 #endif
08002 #if defined(HAVE_SS7)
08003       if (p->sig == SIG_SS7)
08004          break;
08005 #endif   /* defined(HAVE_SS7) */
08006 #ifdef HAVE_OPENR2
08007       if (p->sig == SIG_MFCR2)
08008          break;
08009 #endif
08010    case DAHDI_EVENT_ONHOOK:
08011       if (p->radio) {
08012          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08013          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08014          break;
08015       }
08016       if (p->oprmode < 0)
08017       {
08018          if (p->oprmode != -1) break;
08019          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08020          {
08021             /* Make sure it starts ringing */
08022             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08023             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08024             save_conference(p->oprpeer);
08025             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08026          }
08027          break;
08028       }
08029       switch (p->sig) {
08030       case SIG_FXOLS:
08031       case SIG_FXOGS:
08032       case SIG_FXOKS:
08033          /* Check for some special conditions regarding call waiting */
08034          if (idx == SUB_REAL) {
08035             /* The normal line was hung up */
08036             if (p->subs[SUB_CALLWAIT].owner) {
08037                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
08038                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08039                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08040                unalloc_sub(p, SUB_CALLWAIT);
08041 #if 0
08042                p->subs[idx].needanswer = 0;
08043                p->subs[idx].needringing = 0;
08044 #endif
08045                p->callwaitingrepeat = 0;
08046                p->cidcwexpire = 0;
08047                p->cid_suppress_expire = 0;
08048                p->owner = NULL;
08049                /* Don't start streaming audio yet if the incoming call isn't up yet */
08050                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08051                   p->dialing = 1;
08052                dahdi_ring_phone(p);
08053             } else if (p->subs[SUB_THREEWAY].owner) {
08054                unsigned int mssinceflash;
08055                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08056                   the private structure -- not especially easy or clean */
08057                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08058                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08059                   DLA_UNLOCK(&p->lock);
08060                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08061                   /* We can grab ast and p in that order, without worry.  We should make sure
08062                      nothing seriously bad has happened though like some sort of bizarre double
08063                      masquerade! */
08064                   DLA_LOCK(&p->lock);
08065                   if (p->owner != ast) {
08066                      ast_log(LOG_WARNING, "This isn't good...\n");
08067                      return NULL;
08068                   }
08069                }
08070                if (!p->subs[SUB_THREEWAY].owner) {
08071                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08072                   return NULL;
08073                }
08074                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08075                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08076                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08077                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08078                      hanging up.  Hangup both channels now */
08079                   if (p->subs[SUB_THREEWAY].owner)
08080                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08081                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08082                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08083                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08084                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08085                   if (p->transfer) {
08086                      /* In any case this isn't a threeway call anymore */
08087                      p->subs[SUB_REAL].inthreeway = 0;
08088                      p->subs[SUB_THREEWAY].inthreeway = 0;
08089                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08090                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08091                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08092                         /* Swap subs and dis-own channel */
08093                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08094                         p->owner = NULL;
08095                         /* Ring the phone */
08096                         dahdi_ring_phone(p);
08097                      } else {
08098                         if ((res = attempt_transfer(p)) < 0) {
08099                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08100                            if (p->subs[SUB_THREEWAY].owner)
08101                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08102                         } else if (res) {
08103                            /* Don't actually hang up at this point */
08104                            if (p->subs[SUB_THREEWAY].owner)
08105                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08106                            break;
08107                         }
08108                      }
08109                   } else {
08110                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08111                      if (p->subs[SUB_THREEWAY].owner)
08112                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08113                   }
08114                } else {
08115                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08116                   /* Swap subs and dis-own channel */
08117                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08118                   p->owner = NULL;
08119                   /* Ring the phone */
08120                   dahdi_ring_phone(p);
08121                }
08122             }
08123          } else {
08124             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08125          }
08126          /* Fall through */
08127       default:
08128          dahdi_disable_ec(p);
08129          return NULL;
08130       }
08131       break;
08132    case DAHDI_EVENT_RINGOFFHOOK:
08133       if (p->inalarm) break;
08134       if (p->oprmode < 0)
08135       {
08136          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08137          {
08138             /* Make sure it stops ringing */
08139             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08140             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08141             restore_conference(p->oprpeer);
08142          }
08143          break;
08144       }
08145       if (p->radio)
08146       {
08147          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08148          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08149          break;
08150       }
08151       /* for E911, its supposed to wait for offhook then dial
08152          the second half of the dial string */
08153       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08154          c = strchr(p->dialdest, '/');
08155          if (c)
08156             c++;
08157          else
08158             c = p->dialdest;
08159          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08160          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08161          if (strlen(p->dop.dialstr) > 4) {
08162             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08163             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08164             p->echorest[sizeof(p->echorest) - 1] = '\0';
08165             p->echobreak = 1;
08166             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08167          } else
08168             p->echobreak = 0;
08169          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08170             int saveerr = errno;
08171 
08172             x = DAHDI_ONHOOK;
08173             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08174             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08175             return NULL;
08176             }
08177          p->dialing = 1;
08178          return &p->subs[idx].f;
08179       }
08180       switch (p->sig) {
08181       case SIG_FXOLS:
08182       case SIG_FXOGS:
08183       case SIG_FXOKS:
08184          switch (ast->_state) {
08185          case AST_STATE_RINGING:
08186             dahdi_enable_ec(p);
08187             dahdi_train_ec(p);
08188             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08189             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08190             /* Make sure it stops ringing */
08191             p->subs[SUB_REAL].needringing = 0;
08192             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08193             ast_debug(1, "channel %d answered\n", p->channel);
08194 
08195             /* Cancel any running CallerID spill */
08196             ast_free(p->cidspill);
08197             p->cidspill = NULL;
08198             restore_conference(p);
08199 
08200             p->dialing = 0;
08201             p->callwaitcas = 0;
08202             if (p->confirmanswer) {
08203                /* Ignore answer if "confirm answer" is enabled */
08204                p->subs[idx].f.frametype = AST_FRAME_NULL;
08205                p->subs[idx].f.subclass.integer = 0;
08206             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08207                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08208                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08209                if (res < 0) {
08210                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08211                   p->dop.dialstr[0] = '\0';
08212                   return NULL;
08213                } else {
08214                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08215                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08216                   p->subs[idx].f.subclass.integer = 0;
08217                   p->dialing = 1;
08218                }
08219                p->dop.dialstr[0] = '\0';
08220                ast_setstate(ast, AST_STATE_DIALING);
08221             } else
08222                ast_setstate(ast, AST_STATE_UP);
08223             return &p->subs[idx].f;
08224          case AST_STATE_DOWN:
08225             ast_setstate(ast, AST_STATE_RING);
08226             ast->rings = 1;
08227             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08228             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08229             ast_debug(1, "channel %d picked up\n", p->channel);
08230             return &p->subs[idx].f;
08231          case AST_STATE_UP:
08232             /* Make sure it stops ringing */
08233             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08234             /* Okay -- probably call waiting*/
08235             if (ast_bridged_channel(p->owner))
08236                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08237             p->subs[idx].needunhold = 1;
08238             break;
08239          case AST_STATE_RESERVED:
08240             /* Start up dialtone */
08241             if (has_voicemail(p))
08242                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08243             else
08244                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08245             break;
08246          default:
08247             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08248          }
08249          break;
08250       case SIG_FXSLS:
08251       case SIG_FXSGS:
08252       case SIG_FXSKS:
08253          if (ast->_state == AST_STATE_RING) {
08254             p->ringt = p->ringt_base;
08255          }
08256 
08257          /* If we get a ring then we cannot be in
08258           * reversed polarity. So we reset to idle */
08259          ast_debug(1, "Setting IDLE polarity due "
08260             "to ring. Old polarity was %d\n",
08261             p->polarity);
08262          p->polarity = POLARITY_IDLE;
08263 
08264          /* Fall through */
08265       case SIG_EM:
08266       case SIG_EM_E1:
08267       case SIG_EMWINK:
08268       case SIG_FEATD:
08269       case SIG_FEATDMF:
08270       case SIG_FEATDMF_TA:
08271       case SIG_E911:
08272       case SIG_FGC_CAMA:
08273       case SIG_FGC_CAMAMF:
08274       case SIG_FEATB:
08275       case SIG_SF:
08276       case SIG_SFWINK:
08277       case SIG_SF_FEATD:
08278       case SIG_SF_FEATDMF:
08279       case SIG_SF_FEATB:
08280          if (ast->_state == AST_STATE_PRERING)
08281             ast_setstate(ast, AST_STATE_RING);
08282          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08283             ast_debug(1, "Ring detected\n");
08284             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08285             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08286          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08287             ast_debug(1, "Line answered\n");
08288             if (p->confirmanswer) {
08289                p->subs[idx].f.frametype = AST_FRAME_NULL;
08290                p->subs[idx].f.subclass.integer = 0;
08291             } else {
08292                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08293                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08294                ast_setstate(ast, AST_STATE_UP);
08295             }
08296          } else if (ast->_state != AST_STATE_RING)
08297             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08298          break;
08299       default:
08300          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08301       }
08302       break;
08303    case DAHDI_EVENT_RINGBEGIN:
08304       switch (p->sig) {
08305       case SIG_FXSLS:
08306       case SIG_FXSGS:
08307       case SIG_FXSKS:
08308          if (ast->_state == AST_STATE_RING) {
08309             p->ringt = p->ringt_base;
08310          }
08311          break;
08312       }
08313       break;
08314    case DAHDI_EVENT_RINGERON:
08315       break;
08316    case DAHDI_EVENT_NOALARM:
08317       switch (p->sig) {
08318 #if defined(HAVE_PRI)
08319       case SIG_PRI_LIB_HANDLE_CASES:
08320          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08321          break;
08322 #endif   /* defined(HAVE_PRI) */
08323 #if defined(HAVE_SS7)
08324       case SIG_SS7:
08325          sig_ss7_set_alarm(p->sig_pvt, 0);
08326          break;
08327 #endif   /* defined(HAVE_SS7) */
08328       default:
08329          p->inalarm = 0;
08330          break;
08331       }
08332       handle_clear_alarms(p);
08333       break;
08334    case DAHDI_EVENT_WINKFLASH:
08335       if (p->inalarm) break;
08336       if (p->radio) break;
08337       if (p->oprmode < 0) break;
08338       if (p->oprmode > 1)
08339       {
08340          struct dahdi_params par;
08341 
08342          memset(&par, 0, sizeof(par));
08343          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08344          {
08345             if (!par.rxisoffhook)
08346             {
08347                /* Make sure it stops ringing */
08348                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08349                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08350                save_conference(p);
08351                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08352             }
08353          }
08354          break;
08355       }
08356       /* Remember last time we got a flash-hook */
08357       p->flashtime = ast_tvnow();
08358       switch (mysig) {
08359       case SIG_FXOLS:
08360       case SIG_FXOGS:
08361       case SIG_FXOKS:
08362          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08363             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08364 
08365          /* Cancel any running CallerID spill */
08366          ast_free(p->cidspill);
08367          p->cidspill = NULL;
08368          restore_conference(p);
08369          p->callwaitcas = 0;
08370 
08371          if (idx != SUB_REAL) {
08372             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08373             goto winkflashdone;
08374          }
08375 
08376          if (p->subs[SUB_CALLWAIT].owner) {
08377             /* Swap to call-wait */
08378             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08379             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08380             p->owner = p->subs[SUB_REAL].owner;
08381             ast_debug(1, "Making %s the new owner\n", p->owner->name);
08382             if (p->owner->_state == AST_STATE_RINGING) {
08383                ast_setstate(p->owner, AST_STATE_UP);
08384                p->subs[SUB_REAL].needanswer = 1;
08385             }
08386             p->callwaitingrepeat = 0;
08387             p->cidcwexpire = 0;
08388             p->cid_suppress_expire = 0;
08389             /* Start music on hold if appropriate */
08390             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08391                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08392                   S_OR(p->mohsuggest, NULL),
08393                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08394             }
08395             p->subs[SUB_CALLWAIT].needhold = 1;
08396             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08397                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08398                   S_OR(p->mohsuggest, NULL),
08399                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08400             }
08401             p->subs[SUB_REAL].needunhold = 1;
08402          } else if (!p->subs[SUB_THREEWAY].owner) {
08403             if (!p->threewaycalling) {
08404                /* Just send a flash if no 3-way calling */
08405                p->subs[SUB_REAL].needflash = 1;
08406                goto winkflashdone;
08407             } else if (!check_for_conference(p)) {
08408                char cid_num[256];
08409                char cid_name[256];
08410 
08411                cid_num[0] = 0;
08412                cid_name[0] = 0;
08413                if (p->dahditrcallerid && p->owner) {
08414                   if (p->owner->caller.id.number.valid
08415                      && p->owner->caller.id.number.str) {
08416                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08417                         sizeof(cid_num));
08418                   }
08419                   if (p->owner->caller.id.name.valid
08420                      && p->owner->caller.id.name.str) {
08421                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08422                         sizeof(cid_name));
08423                   }
08424                }
08425                /* XXX This section needs much more error checking!!! XXX */
08426                /* Start a 3-way call if feasible */
08427                if (!((ast->pbx) ||
08428                   (ast->_state == AST_STATE_UP) ||
08429                   (ast->_state == AST_STATE_RING))) {
08430                   ast_debug(1, "Flash when call not up or ringing\n");
08431                   goto winkflashdone;
08432                }
08433                if (alloc_sub(p, SUB_THREEWAY)) {
08434                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08435                   goto winkflashdone;
08436                }
08437                /* Make new channel */
08438                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08439                if (p->dahditrcallerid) {
08440                   if (!p->origcid_num)
08441                      p->origcid_num = ast_strdup(p->cid_num);
08442                   if (!p->origcid_name)
08443                      p->origcid_name = ast_strdup(p->cid_name);
08444                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08445                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08446                }
08447                /* Swap things around between the three-way and real call */
08448                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08449                /* Disable echo canceller for better dialing */
08450                dahdi_disable_ec(p);
08451                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08452                if (res)
08453                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08454                p->owner = chan;
08455                if (!chan) {
08456                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08457                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08458                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08459                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08460                   dahdi_enable_ec(p);
08461                   ast_hangup(chan);
08462                } else {
08463                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08464 
08465                   /* Start music on hold if appropriate */
08466                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08467                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08468                         S_OR(p->mohsuggest, NULL),
08469                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08470                   }
08471                   p->subs[SUB_THREEWAY].needhold = 1;
08472                }
08473             }
08474          } else {
08475             /* Already have a 3 way call */
08476             if (p->subs[SUB_THREEWAY].inthreeway) {
08477                /* Call is already up, drop the last person */
08478                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08479                /* If the primary call isn't answered yet, use it */
08480                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08481                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08482                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08483                   p->owner = p->subs[SUB_REAL].owner;
08484                }
08485                /* Drop the last call and stop the conference */
08486                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08487                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08488                p->subs[SUB_REAL].inthreeway = 0;
08489                p->subs[SUB_THREEWAY].inthreeway = 0;
08490             } else {
08491                /* Lets see what we're up to */
08492                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08493                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08494                   int otherindex = SUB_THREEWAY;
08495 
08496                   ast_verb(3, "Building conference call with %s and %s\n",
08497                      p->subs[SUB_THREEWAY].owner->name,
08498                      p->subs[SUB_REAL].owner->name);
08499                   /* Put them in the threeway, and flip */
08500                   p->subs[SUB_THREEWAY].inthreeway = 1;
08501                   p->subs[SUB_REAL].inthreeway = 1;
08502                   if (ast->_state == AST_STATE_UP) {
08503                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08504                      otherindex = SUB_REAL;
08505                   }
08506                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08507                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08508                   p->subs[otherindex].needunhold = 1;
08509                   p->owner = p->subs[SUB_REAL].owner;
08510                } else {
08511                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08512                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08513                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08514                   p->owner = p->subs[SUB_REAL].owner;
08515                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08516                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08517                   p->subs[SUB_REAL].needunhold = 1;
08518                   dahdi_enable_ec(p);
08519                }
08520             }
08521          }
08522 winkflashdone:
08523          update_conf(p);
08524          break;
08525       case SIG_EM:
08526       case SIG_EM_E1:
08527       case SIG_FEATD:
08528       case SIG_SF:
08529       case SIG_SFWINK:
08530       case SIG_SF_FEATD:
08531       case SIG_FXSLS:
08532       case SIG_FXSGS:
08533          if (p->dialing)
08534             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08535          else
08536             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08537          break;
08538       case SIG_FEATDMF_TA:
08539          switch (p->whichwink) {
08540          case 0:
08541             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08542                S_COR(p->owner->caller.ani.number.valid,
08543                   p->owner->caller.ani.number.str, ""));
08544             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08545                p->owner->caller.ani2,
08546                S_COR(p->owner->caller.ani.number.valid,
08547                   p->owner->caller.ani.number.str, ""));
08548             break;
08549          case 1:
08550             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08551             break;
08552          case 2:
08553             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08554             return NULL;
08555          }
08556          p->whichwink++;
08557          /* Fall through */
08558       case SIG_FEATDMF:
08559       case SIG_E911:
08560       case SIG_FGC_CAMAMF:
08561       case SIG_FGC_CAMA:
08562       case SIG_FEATB:
08563       case SIG_SF_FEATDMF:
08564       case SIG_SF_FEATB:
08565       case SIG_EMWINK:
08566          /* FGD MF and EMWINK *Must* wait for wink */
08567          if (!ast_strlen_zero(p->dop.dialstr)) {
08568             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08569             if (res < 0) {
08570                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08571                p->dop.dialstr[0] = '\0';
08572                return NULL;
08573             } else
08574                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08575          }
08576          p->dop.dialstr[0] = '\0';
08577          break;
08578       default:
08579          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08580       }
08581       break;
08582    case DAHDI_EVENT_HOOKCOMPLETE:
08583       if (p->inalarm) break;
08584       if ((p->radio || (p->oprmode < 0))) break;
08585       if (p->waitingfordt.tv_sec) break;
08586       switch (mysig) {
08587       case SIG_FXSLS:  /* only interesting for FXS */
08588       case SIG_FXSGS:
08589       case SIG_FXSKS:
08590       case SIG_EM:
08591       case SIG_EM_E1:
08592       case SIG_EMWINK:
08593       case SIG_FEATD:
08594       case SIG_SF:
08595       case SIG_SFWINK:
08596       case SIG_SF_FEATD:
08597          if (!ast_strlen_zero(p->dop.dialstr)) {
08598             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08599             if (res < 0) {
08600                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08601                p->dop.dialstr[0] = '\0';
08602                return NULL;
08603             } else
08604                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08605          }
08606          p->dop.dialstr[0] = '\0';
08607          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08608          break;
08609       case SIG_FEATDMF:
08610       case SIG_FEATDMF_TA:
08611       case SIG_E911:
08612       case SIG_FGC_CAMA:
08613       case SIG_FGC_CAMAMF:
08614       case SIG_FEATB:
08615       case SIG_SF_FEATDMF:
08616       case SIG_SF_FEATB:
08617          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08618          break;
08619       default:
08620          break;
08621       }
08622       break;
08623    case DAHDI_EVENT_POLARITY:
08624       /*
08625        * If we get a Polarity Switch event, check to see
08626        * if we should change the polarity state and
08627        * mark the channel as UP or if this is an indication
08628        * of remote end disconnect.
08629        */
08630       if (p->polarity == POLARITY_IDLE) {
08631          p->polarity = POLARITY_REV;
08632          if (p->answeronpolarityswitch &&
08633             ((ast->_state == AST_STATE_DIALING) ||
08634             (ast->_state == AST_STATE_RINGING))) {
08635             ast_debug(1, "Answering on polarity switch!\n");
08636             ast_setstate(p->owner, AST_STATE_UP);
08637             if (p->hanguponpolarityswitch) {
08638                p->polaritydelaytv = ast_tvnow();
08639             }
08640          } else
08641             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08642       }
08643       /* Removed else statement from here as it was preventing hangups from ever happening*/
08644       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08645       if (p->hanguponpolarityswitch &&
08646          (p->polarityonanswerdelay > 0) &&
08647          (p->polarity == POLARITY_REV) &&
08648          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08649          /* Added log_debug information below to provide a better indication of what is going on */
08650          ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08651 
08652          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08653             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08654             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08655             p->polarity = POLARITY_IDLE;
08656          } else
08657             ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
08658 
08659       } else {
08660          p->polarity = POLARITY_IDLE;
08661          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08662       }
08663       /* Added more log_debug information below to provide a better indication of what is going on */
08664       ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08665       break;
08666    default:
08667       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08668    }
08669    return &p->subs[idx].f;
08670 }

static int dahdi_hangup ( struct ast_channel ast  )  [static]

Definition at line 6088 of file chan_dahdi.c.

References ast_channel::_state, analog_hangup(), analog_lib_handles(), 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::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cid_tag, dahdi_pvt::cidcwexpire, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_ast_cause_to_r2_cause(), dahdi_confmute(), dahdi_disable_ec(), dahdi_get_index, dahdi_r2_disconnect_call(), dahdi_set_hook(), dahdi_setlinear(), dahdi_sig_pri_lib_handles(), dahdi_pvt::destroy, destroy_channel(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::didtdd, dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, analog_pvt::fxsoffhookstate, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_pvt::law, dahdi_pvt::law_default, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_forced_release, dahdi_pvt::mfcr2call, dahdi_pvt::mohsuggest, dahdi_pvt::muting, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, num_restart_pending, 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::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::rdnis, reset_conf(), restart_monitor(), dahdi_pvt::restartpending, restore_gains(), revert_fax_buffers(), dahdi_pvt::ringt, S_OR, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, sig_pri_hangup(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_hangup(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), update_conf(), and dahdi_pvt::waitingfordt.

06089 {
06090    int res = 0;
06091    int idx,x;
06092    int law;
06093    /*static int restore_gains(struct dahdi_pvt *p);*/
06094    struct dahdi_pvt *p = ast->tech_pvt;
06095    struct dahdi_params par;
06096 
06097    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06098    if (!ast->tech_pvt) {
06099       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06100       return 0;
06101    }
06102 
06103    ast_mutex_lock(&p->lock);
06104    p->exten[0] = '\0';
06105    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06106       dahdi_confmute(p, 0);
06107       restore_gains(p);
06108       p->ignoredtmf = 0;
06109       p->waitingfordt.tv_sec = 0;
06110 
06111       res = analog_hangup(p->sig_pvt, ast);
06112       revert_fax_buffers(p, ast);
06113 
06114       goto hangup_out;
06115    } else {
06116       p->cid_num[0] = '\0';
06117       p->cid_name[0] = '\0';
06118       p->cid_subaddr[0] = '\0';
06119    }
06120 
06121 #if defined(HAVE_PRI)
06122    if (dahdi_sig_pri_lib_handles(p->sig)) {
06123       x = 1;
06124       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06125 
06126       dahdi_confmute(p, 0);
06127       p->muting = 0;
06128       restore_gains(p);
06129       if (p->dsp) {
06130          ast_dsp_free(p->dsp);
06131          p->dsp = NULL;
06132       }
06133       p->ignoredtmf = 0;
06134 
06135       /* Real channel, do some fixup */
06136       p->subs[SUB_REAL].owner = NULL;
06137       p->subs[SUB_REAL].needbusy = 0;
06138       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06139 
06140       p->owner = NULL;
06141       p->cid_tag[0] = '\0';
06142       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06143       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06144       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06145       p->outgoing = 0;
06146       p->digital = 0;
06147       p->faxhandled = 0;
06148       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06149 
06150       revert_fax_buffers(p, ast);
06151 
06152       p->law = p->law_default;
06153       law = p->law_default;
06154       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06155       if (res < 0) {
06156          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06157             p->channel, strerror(errno));
06158       }
06159 
06160       sig_pri_hangup(p->sig_pvt, ast);
06161 
06162       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06163       dahdi_disable_ec(p);
06164 
06165       x = 0;
06166       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06167       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06168 
06169       p->rdnis[0] = '\0';
06170       update_conf(p);
06171       reset_conf(p);
06172 
06173       /* Restore data mode */
06174       x = 0;
06175       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06176 
06177       if (num_restart_pending == 0) {
06178          restart_monitor();
06179       }
06180       goto hangup_out;
06181    }
06182 #endif   /* defined(HAVE_PRI) */
06183 
06184 #if defined(HAVE_SS7)
06185    if (p->sig == SIG_SS7) {
06186       x = 1;
06187       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06188 
06189       dahdi_confmute(p, 0);
06190       p->muting = 0;
06191       restore_gains(p);
06192       if (p->dsp) {
06193          ast_dsp_free(p->dsp);
06194          p->dsp = NULL;
06195       }
06196       p->ignoredtmf = 0;
06197 
06198       /* Real channel, do some fixup */
06199       p->subs[SUB_REAL].owner = NULL;
06200       p->subs[SUB_REAL].needbusy = 0;
06201       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06202 
06203       p->owner = NULL;
06204       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06205       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06206       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06207       p->outgoing = 0;
06208       p->digital = 0;
06209       p->faxhandled = 0;
06210       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06211 
06212       revert_fax_buffers(p, ast);
06213 
06214       p->law = p->law_default;
06215       law = p->law_default;
06216       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06217       if (res < 0) {
06218          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06219             p->channel, strerror(errno));
06220       }
06221 
06222       sig_ss7_hangup(p->sig_pvt, ast);
06223 
06224       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06225       dahdi_disable_ec(p);
06226 
06227       x = 0;
06228       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06229       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06230 
06231       update_conf(p);
06232       reset_conf(p);
06233 
06234       /* Restore data mode */
06235       x = 0;
06236       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06237 
06238       if (num_restart_pending == 0) {
06239          restart_monitor();
06240       }
06241       goto hangup_out;
06242    }
06243 #endif   /* defined(HAVE_SS7) */
06244 
06245    idx = dahdi_get_index(ast, p, 1);
06246 
06247    dahdi_confmute(p, 0);
06248    p->muting = 0;
06249    restore_gains(p);
06250    if (p->origcid_num) {
06251       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06252       ast_free(p->origcid_num);
06253       p->origcid_num = NULL;
06254    }
06255    if (p->origcid_name) {
06256       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06257       ast_free(p->origcid_name);
06258       p->origcid_name = NULL;
06259    }
06260    if (p->dsp)
06261       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06262 
06263    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06264       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06265    p->ignoredtmf = 0;
06266 
06267    if (idx > -1) {
06268       /* Real channel, do some fixup */
06269       p->subs[idx].owner = NULL;
06270       p->subs[idx].needanswer = 0;
06271       p->subs[idx].needflash = 0;
06272       p->subs[idx].needringing = 0;
06273       p->subs[idx].needbusy = 0;
06274       p->subs[idx].needcongestion = 0;
06275       p->subs[idx].linear = 0;
06276       p->polarity = POLARITY_IDLE;
06277       dahdi_setlinear(p->subs[idx].dfd, 0);
06278       if (idx == SUB_REAL) {
06279          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06280             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06281             if (p->subs[SUB_CALLWAIT].inthreeway) {
06282                /* We had flipped over to answer a callwait and now it's gone */
06283                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06284                /* Move to the call-wait, but un-own us until they flip back. */
06285                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06286                unalloc_sub(p, SUB_CALLWAIT);
06287                p->owner = NULL;
06288             } else {
06289                /* The three way hung up, but we still have a call wait */
06290                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06291                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06292                unalloc_sub(p, SUB_THREEWAY);
06293                if (p->subs[SUB_REAL].inthreeway) {
06294                   /* This was part of a three way call.  Immediately make way for
06295                      another call */
06296                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06297                   p->owner = p->subs[SUB_REAL].owner;
06298                } else {
06299                   /* This call hasn't been completed yet...  Set owner to NULL */
06300                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06301                   p->owner = NULL;
06302                }
06303                p->subs[SUB_REAL].inthreeway = 0;
06304             }
06305          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06306             /* Move to the call-wait and switch back to them. */
06307             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06308             unalloc_sub(p, SUB_CALLWAIT);
06309             p->owner = p->subs[SUB_REAL].owner;
06310             if (p->owner->_state != AST_STATE_UP)
06311                p->subs[SUB_REAL].needanswer = 1;
06312             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06313                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06314          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06315             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06316             unalloc_sub(p, SUB_THREEWAY);
06317             if (p->subs[SUB_REAL].inthreeway) {
06318                /* This was part of a three way call.  Immediately make way for
06319                   another call */
06320                ast_debug(1, "Call was complete, setting owner to former third call\n");
06321                p->owner = p->subs[SUB_REAL].owner;
06322             } else {
06323                /* This call hasn't been completed yet...  Set owner to NULL */
06324                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06325                p->owner = NULL;
06326             }
06327             p->subs[SUB_REAL].inthreeway = 0;
06328          }
06329       } else if (idx == SUB_CALLWAIT) {
06330          /* Ditch the holding callwait call, and immediately make it availabe */
06331          if (p->subs[SUB_CALLWAIT].inthreeway) {
06332             /* This is actually part of a three way, placed on hold.  Place the third part
06333                on music on hold now */
06334             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06335                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06336                   S_OR(p->mohsuggest, NULL),
06337                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06338             }
06339             p->subs[SUB_THREEWAY].inthreeway = 0;
06340             /* Make it the call wait now */
06341             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06342             unalloc_sub(p, SUB_THREEWAY);
06343          } else
06344             unalloc_sub(p, SUB_CALLWAIT);
06345       } else if (idx == SUB_THREEWAY) {
06346          if (p->subs[SUB_CALLWAIT].inthreeway) {
06347             /* The other party of the three way call is currently in a call-wait state.
06348                Start music on hold for them, and take the main guy out of the third call */
06349             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06350                ast_queue_control_data(p->subs[SUB_CALLWAIT].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_CALLWAIT].inthreeway = 0;
06355          }
06356          p->subs[SUB_REAL].inthreeway = 0;
06357          /* If this was part of a three way call index, let us make
06358             another three way call */
06359          unalloc_sub(p, SUB_THREEWAY);
06360       } else {
06361          /* This wasn't any sort of call, but how are we an index? */
06362          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06363       }
06364    }
06365 
06366    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06367       p->owner = NULL;
06368       p->ringt = 0;
06369       p->distinctivering = 0;
06370       p->confirmanswer = 0;
06371       p->outgoing = 0;
06372       p->digital = 0;
06373       p->faxhandled = 0;
06374       p->pulsedial = 0;
06375       if (p->dsp) {
06376          ast_dsp_free(p->dsp);
06377          p->dsp = NULL;
06378       }
06379 
06380       revert_fax_buffers(p, ast);
06381 
06382       p->law = p->law_default;
06383       law = p->law_default;
06384       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06385       if (res < 0)
06386          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06387       /* Perform low level hangup if no owner left */
06388 #ifdef HAVE_OPENR2
06389       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06390          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06391          /* If it's an incoming call, check the mfcr2_forced_release setting */
06392          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06393             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06394          } else {
06395             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06396             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06397             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06398                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06399             dahdi_r2_disconnect_call(p, r2cause);
06400          }
06401       } else if (p->mfcr2call) {
06402          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06403          /* since ast_request() was called but not ast_call() we have not yet dialed
06404          and the openr2 stack will not call on_call_end callback, we need to unset
06405          the mfcr2call flag and bump the monitor count so the monitor thread can take
06406          care of this channel events from now on */
06407          p->mfcr2call = 0;
06408       }
06409 #endif
06410       switch (p->sig) {
06411       case SIG_SS7:
06412       case SIG_MFCR2:
06413       case SIG_PRI_LIB_HANDLE_CASES:
06414       case 0:
06415          break;
06416       default:
06417          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06418          break;
06419       }
06420       if (res < 0) {
06421          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06422       }
06423       switch (p->sig) {
06424       case SIG_FXOGS:
06425       case SIG_FXOLS:
06426       case SIG_FXOKS:
06427          memset(&par, 0, sizeof(par));
06428          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06429          if (!res) {
06430             struct analog_pvt *analog_p = p->sig_pvt;
06431 #if 0
06432             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06433 #endif
06434             /* If they're off hook, try playing congestion */
06435             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06436                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06437             else
06438                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06439             analog_p->fxsoffhookstate = par.rxisoffhook;
06440          }
06441          break;
06442       case SIG_FXSGS:
06443       case SIG_FXSLS:
06444       case SIG_FXSKS:
06445          /* Make sure we're not made available for at least two seconds assuming
06446          we were actually used for an inbound or outbound call. */
06447          if (ast->_state != AST_STATE_RESERVED) {
06448             time(&p->guardtime);
06449             p->guardtime += 2;
06450          }
06451          break;
06452       default:
06453          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06454          break;
06455       }
06456       if (p->sig)
06457          dahdi_disable_ec(p);
06458       x = 0;
06459       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06460       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06461       p->didtdd = 0;
06462       p->callwaitcas = 0;
06463       p->callwaiting = p->permcallwaiting;
06464       p->hidecallerid = p->permhidecallerid;
06465       p->waitingfordt.tv_sec = 0;
06466       p->dialing = 0;
06467       p->rdnis[0] = '\0';
06468       update_conf(p);
06469       reset_conf(p);
06470       /* Restore data mode */
06471       switch (p->sig) {
06472       case SIG_PRI_LIB_HANDLE_CASES:
06473       case SIG_SS7:
06474          x = 0;
06475          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06476          break;
06477       default:
06478          break;
06479       }
06480       if (num_restart_pending == 0)
06481          restart_monitor();
06482    }
06483 
06484    p->callwaitingrepeat = 0;
06485    p->cidcwexpire = 0;
06486    p->cid_suppress_expire = 0;
06487    p->oprmode = 0;
06488 hangup_out:
06489    ast->tech_pvt = NULL;
06490    ast_free(p->cidspill);
06491    p->cidspill = NULL;
06492 
06493    ast_mutex_unlock(&p->lock);
06494    ast_verb(3, "Hungup '%s'\n", ast->name);
06495 
06496    ast_mutex_lock(&iflock);
06497    if (p->restartpending) {
06498       num_restart_pending--;
06499    }
06500 
06501    if (p->destroy) {
06502       destroy_channel(p, 0);
06503    }
06504    ast_mutex_unlock(&iflock);
06505 
06506    ast_module_unref(ast_module_info->self);
06507    return 0;
06508 }

static void dahdi_iflist_extract ( struct dahdi_pvt pvt  )  [static]

Definition at line 5489 of file chan_dahdi.c.

References DAHDI_IFLIST_NONE, ifend, iflist, dahdi_pvt::next, dahdi_pvt::prev, and dahdi_pvt::which_iflist.

Referenced by destroy_dahdi_pvt().

05490 {
05491    /* Extract from the forward chain. */
05492    if (pvt->prev) {
05493       pvt->prev->next = pvt->next;
05494    } else if (iflist == pvt) {
05495       /* Node is at the head of the list. */
05496       iflist = pvt->next;
05497    }
05498 
05499    /* Extract from the reverse chain. */
05500    if (pvt->next) {
05501       pvt->next->prev = pvt->prev;
05502    } else if (ifend == pvt) {
05503       /* Node is at the end of the list. */
05504       ifend = pvt->prev;
05505    }
05506 
05507    /* Node is no longer in the list. */
05508    pvt->which_iflist = DAHDI_IFLIST_NONE;
05509    pvt->prev = NULL;
05510    pvt->next = NULL;
05511 }

static void dahdi_iflist_insert ( struct dahdi_pvt pvt  )  [static]

Definition at line 5439 of file chan_dahdi.c.

References dahdi_pvt::channel, DAHDI_IFLIST_MAIN, iflist, dahdi_pvt::next, dahdi_pvt::prev, and dahdi_pvt::which_iflist.

Referenced by duplicate_pseudo().

05440 {
05441    struct dahdi_pvt *cur;
05442 
05443    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05444 
05445    /* Find place in middle of list for the new interface. */
05446    for (cur = iflist; cur; cur = cur->next) {
05447       if (pvt->channel < cur->channel) {
05448          /* New interface goes before the current interface. */
05449          pvt->prev = cur->prev;
05450          pvt->next = cur;
05451          if (cur->prev) {
05452             /* Insert into the middle of the list. */
05453             cur->prev->next = pvt;
05454          } else {
05455             /* Insert at head of list. */
05456             iflist = pvt;
05457          }
05458          cur->prev = pvt;
05459          return;
05460       }
05461    }
05462 
05463    /* New interface goes onto the end of the list */
05464    pvt->prev = ifend;
05465    pvt->next = NULL;
05466    if (ifend) {
05467       ifend->next = pvt;
05468    }
05469    ifend = pvt;
05470    if (!iflist) {
05471       /* List was empty */
05472       iflist = pvt;
05473    }
05474 }

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

Definition at line 9311 of file chan_dahdi.c.

References ast_channel::_state, AST_CAUSE_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, 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_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, dahdi_get_index, dahdi_set_hook(), dahdi_subchannel::dfd, dahdi_pvt::dop, errno, ast_channel::hangupcause, ISTRUNK, dahdi_pvt::lock, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mohinterpret, ast_channel::name, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, sig_pri_indicate(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_indicate(), SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

09312 {
09313    struct dahdi_pvt *p = chan->tech_pvt;
09314    int res=-1;
09315    int idx;
09316    int func = DAHDI_FLASH;
09317 
09318    ast_mutex_lock(&p->lock);
09319    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09320    switch (p->sig) {
09321 #if defined(HAVE_PRI)
09322    case SIG_PRI_LIB_HANDLE_CASES:
09323       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09324       ast_mutex_unlock(&p->lock);
09325       return res;
09326 #endif   /* defined(HAVE_PRI) */
09327 #if defined(HAVE_SS7)
09328    case SIG_SS7:
09329       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09330       ast_mutex_unlock(&p->lock);
09331       return res;
09332 #endif   /* defined(HAVE_SS7) */
09333    default:
09334       break;
09335    }
09336 #ifdef HAVE_OPENR2
09337    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09338       ast_mutex_unlock(&p->lock);
09339       /* if this is an R2 call and the call is not yet accepted, we don't want the
09340          tone indications to mess up with the MF tones */
09341       return 0;
09342    }
09343 #endif
09344    idx = dahdi_get_index(chan, p, 0);
09345    if (idx == SUB_REAL) {
09346       switch (condition) {
09347       case AST_CONTROL_BUSY:
09348          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09349          break;
09350       case AST_CONTROL_RINGING:
09351          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09352 
09353          if (chan->_state != AST_STATE_UP) {
09354             if ((chan->_state != AST_STATE_RING) ||
09355                ((p->sig != SIG_FXSKS) &&
09356              (p->sig != SIG_FXSLS) &&
09357              (p->sig != SIG_FXSGS)))
09358             ast_setstate(chan, AST_STATE_RINGING);
09359          }
09360          break;
09361       case AST_CONTROL_INCOMPLETE:
09362          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09363          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09364          res = 0;
09365          break;
09366       case AST_CONTROL_PROCEEDING:
09367          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09368          /* don't continue in ast_indicate */
09369          res = 0;
09370          break;
09371       case AST_CONTROL_PROGRESS:
09372          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09373          /* don't continue in ast_indicate */
09374          res = 0;
09375          break;
09376       case AST_CONTROL_CONGESTION:
09377          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09378          switch (chan->hangupcause) {
09379          case AST_CAUSE_USER_BUSY:
09380          case AST_CAUSE_NORMAL_CLEARING:
09381          case 0:/* Cause has not been set. */
09382             /* Supply a more appropriate cause. */
09383             chan->hangupcause = AST_CAUSE_CONGESTION;
09384             break;
09385          default:
09386             break;
09387          }
09388          break;
09389       case AST_CONTROL_HOLD:
09390          ast_moh_start(chan, data, p->mohinterpret);
09391          break;
09392       case AST_CONTROL_UNHOLD:
09393          ast_moh_stop(chan);
09394          break;
09395       case AST_CONTROL_RADIO_KEY:
09396          if (p->radio)
09397             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09398          res = 0;
09399          break;
09400       case AST_CONTROL_RADIO_UNKEY:
09401          if (p->radio)
09402             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09403          res = 0;
09404          break;
09405       case AST_CONTROL_FLASH:
09406          /* flash hookswitch */
09407          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09408             /* Clear out the dial buffer */
09409             p->dop.dialstr[0] = '\0';
09410             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09411                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09412                   chan->name, strerror(errno));
09413             } else
09414                res = 0;
09415          } else
09416             res = 0;
09417          break;
09418       case AST_CONTROL_SRCUPDATE:
09419          res = 0;
09420          break;
09421       case -1:
09422          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09423          break;
09424       }
09425    } else {
09426       res = 0;
09427    }
09428    ast_mutex_unlock(&p->lock);
09429    return res;
09430 }

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

Definition at line 7134 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, and dahdi_pvt::slaves.

Referenced by dahdi_bridge().

07134                                                                           {
07135    int x;
07136    if (!slave || !master) {
07137       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07138       return;
07139    }
07140    for (x = 0; x < MAX_SLAVES; x++) {
07141       if (!master->slaves[x]) {
07142          master->slaves[x] = slave;
07143          break;
07144       }
07145    }
07146    if (x >= MAX_SLAVES) {
07147       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07148       master->slaves[MAX_SLAVES - 1] = slave;
07149    }
07150    if (slave->master)
07151       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07152    slave->master = master;
07153 
07154    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07155 }

static void dahdi_lock_sub_owner ( struct dahdi_pvt pvt,
int  sub_idx 
) [static]

Definition at line 3719 of file chan_dahdi.c.

References ast_channel_trylock, dahdi_subchannel::owner, and dahdi_pvt::subs.

Referenced by wakeup_sub().

03720 {
03721    for (;;) {
03722       if (!pvt->subs[sub_idx].owner) {
03723          /* No subchannel owner pointer */
03724          break;
03725       }
03726       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03727          /* Got subchannel owner lock */
03728          break;
03729       }
03730       /* We must unlock the private to avoid the possibility of a deadlock */
03731       DEADLOCK_AVOIDANCE(&pvt->lock);
03732    }
03733 }

static struct ast_channel * dahdi_new ( struct dahdi_pvt i,
int  state,
int  startpbx,
int  idx,
int  law,
const char *  linkedid 
) [static]

Definition at line 9480 of file chan_dahdi.c.

References accountcode, dahdi_pvt::accountcode, dahdi_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, dahdi_pvt::amaflags, analog_lib_handles(), ast_party_caller::ani, ast_party_caller::ani2, AST_ADSI_UNAVAILABLE, ast_cc_copy_config_params(), ast_channel_alloc, ast_channel_cc_params_init(), AST_CHANNEL_NAME, ast_channel_set_fd(), ast_copy_string(), ast_debug, AST_DEVICE_UNKNOWN, ast_devstate_changed_literal(), ast_dsp_new(), ast_dsp_set_busy_compare(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_digitmode(), ast_dsp_set_features(), ast_dsp_set_threshold(), AST_FORMAT_ALAW, AST_FORMAT_ULAW, ast_free, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), AST_STATE_RING, ast_str_buffer(), ast_strdup, ast_string_field_set, ast_strlen_zero(), dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::call_forward, ast_channel::caller, dahdi_pvt::callgroup, ast_channel::callgroup, dahdi_pvt::callingpres, dahdi_pvt::callprogress, CALLPROGRESS_FAX_INCOMING, CALLPROGRESS_FAX_OUTGOING, CALLPROGRESS_PROGRESS, CANBUSYDETECT, CANPROGRESSDETECT, sig_pri_span::cc_params, dahdi_pvt::cc_params, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::cid_ani, dahdi_pvt::cid_ani2, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_tag, dahdi_pvt::cid_ton, ast_channel::context, dahdi_pvt::context, create_channel_name(), dahdi_ami_channel_event(), dahdi_confmute(), dahdi_setlinear(), dahdi_sig_pri_lib_handles(), dahdi_tech, dahdi_subchannel::dfd, ast_channel::dialed, 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, ast_channel::exten, dahdi_pvt::exten, dahdi_pvt::fake_event, ast_party_redirecting::from, global_jbconf, dahdi_pvt::hardwaredtmf, ast_party_caller::id, language, dahdi_pvt::language, dahdi_pvt::law, dahdi_pvt::law_default, dahdi_subchannel::linear, dahdi_pvt::mfcr2_recvd_category, dahdi_pvt::mfcr2call, dahdi_pvt::muting, ast_variable::name, ast_party_id::name, ast_channel::name, ast_channel::nativeformats, NEED_MFDETECT, ast_variable::next, ast_party_dialed::number, ast_party_id::number, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, parkinglot, dahdi_pvt::parkinglot, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_channel::pickupgroup, ast_party_number::plan, ast_party_number::presentation, ast_party_name::presentation, dahdi_pvt::pri, progzone, dahdi_pvt::radio, ast_channel::rawreadformat, ast_channel::rawwriteformat, dahdi_pvt::rdnis, ast_channel::readformat, ast_channel::redirecting, ast_channel::rings, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_PRI_LIB_HANDLE_CASES, SIG_SS7, dahdi_pvt::silencethreshold, ast_party_dialed::str, ast_party_number::str, SUB_REAL, subnames, dahdi_pvt::subs, ast_party_id::tag, ast_channel::tech, ast_channel::tech_pvt, ast_party_number::valid, ast_variable::value, dahdi_pvt::vars, dahdi_pvt::waitfordialtone, and ast_channel::writeformat.

Referenced by dahdi_handle_event(), dahdi_r2_on_call_accepted(), dahdi_r2_on_call_offered(), dahdi_request(), handle_init_event(), mwi_thread(), my_new_analog_ast_channel(), my_new_pri_ast_channel(), my_new_ss7_ast_channel(), and register_translator().

09481 {
09482    struct ast_channel *tmp;
09483    format_t deflaw;
09484    int x;
09485    int features;
09486    struct ast_str *chan_name;
09487    struct ast_variable *v;
09488    char *dashptr;
09489    char device_name[AST_CHANNEL_NAME];
09490 
09491    if (i->subs[idx].owner) {
09492       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09493       return NULL;
09494    }
09495 
09496 #if defined(HAVE_PRI)
09497    /*
09498     * The dnid has been stuffed with the called-number[:subaddress]
09499     * by dahdi_request() for outgoing calls.
09500     */
09501    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09502 #else
09503    chan_name = create_channel_name(i);
09504 #endif   /* defined(HAVE_PRI) */
09505    if (!chan_name) {
09506       return NULL;
09507    }
09508 
09509    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, linkedid, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
09510    ast_free(chan_name);
09511    if (!tmp)
09512       return NULL;
09513    tmp->tech = &dahdi_tech;
09514 #if defined(HAVE_PRI)
09515    if (i->pri) {
09516       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09517    }
09518 #endif   /* defined(HAVE_PRI) */
09519    ast_channel_cc_params_init(tmp, i->cc_params);
09520    if (law) {
09521       i->law = law;
09522       if (law == DAHDI_LAW_ALAW) {
09523          deflaw = AST_FORMAT_ALAW;
09524       } else {
09525          deflaw = AST_FORMAT_ULAW;
09526       }
09527    } else {
09528       switch (i->sig) {
09529       case SIG_PRI_LIB_HANDLE_CASES:
09530          /* Make sure companding law is known. */
09531          i->law = (i->law_default == DAHDI_LAW_ALAW)
09532             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09533          break;
09534       default:
09535          i->law = i->law_default;
09536          break;
09537       }
09538       if (i->law_default == DAHDI_LAW_ALAW) {
09539          deflaw = AST_FORMAT_ALAW;
09540       } else {
09541          deflaw = AST_FORMAT_ULAW;
09542       }
09543    }
09544    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09545    tmp->nativeformats = deflaw;
09546    /* Start out assuming ulaw since it's smaller :) */
09547    tmp->rawreadformat = deflaw;
09548    tmp->readformat = deflaw;
09549    tmp->rawwriteformat = deflaw;
09550    tmp->writeformat = deflaw;
09551    i->subs[idx].linear = 0;
09552    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09553    features = 0;
09554    if (idx == SUB_REAL) {
09555       if (i->busydetect && CANBUSYDETECT(i))
09556          features |= DSP_FEATURE_BUSY_DETECT;
09557       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09558          features |= DSP_FEATURE_CALL_PROGRESS;
09559       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09560          features |= DSP_FEATURE_WAITDIALTONE;
09561       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09562          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09563          features |= DSP_FEATURE_FAX_DETECT;
09564       }
09565       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09566       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09567          i->hardwaredtmf = 0;
09568          features |= DSP_FEATURE_DIGIT_DETECT;
09569       } else if (NEED_MFDETECT(i)) {
09570          i->hardwaredtmf = 1;
09571          features |= DSP_FEATURE_DIGIT_DETECT;
09572       }
09573    }
09574    if (features) {
09575       if (i->dsp) {
09576          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09577       } else {
09578          if (i->channel != CHAN_PSEUDO)
09579             i->dsp = ast_dsp_new();
09580          else
09581             i->dsp = NULL;
09582          if (i->dsp) {
09583             i->dsp_features = features;
09584 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09585             /* We cannot do progress detection until receive PROGRESS message */
09586             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09587                /* Remember requested DSP features, don't treat
09588                   talking as ANSWER */
09589                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09590                features = 0;
09591             }
09592 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09593             ast_dsp_set_features(i->dsp, features);
09594             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09595             if (!ast_strlen_zero(progzone))
09596                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09597             if (i->busydetect && CANBUSYDETECT(i)) {
09598                if(i->silencethreshold > 0)
09599                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
09600                ast_dsp_set_busy_count(i->dsp, i->busycount);
09601                if(i->busytonelength > 0)
09602                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
09603                if((i->busytonelength == i->busyquietlength) && i->busycompare)
09604                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
09605             }
09606          }
09607       }
09608    }
09609 
09610    if (state == AST_STATE_RING)
09611       tmp->rings = 1;
09612    tmp->tech_pvt = i;
09613    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09614       /* Only FXO signalled stuff can be picked up */
09615       tmp->callgroup = i->callgroup;
09616       tmp->pickupgroup = i->pickupgroup;
09617    }
09618    if (!ast_strlen_zero(i->parkinglot))
09619       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09620    if (!ast_strlen_zero(i->language))
09621       ast_string_field_set(tmp, language, i->language);
09622    if (!i->owner)
09623       i->owner = tmp;
09624    if (!ast_strlen_zero(i->accountcode))
09625       ast_string_field_set(tmp, accountcode, i->accountcode);
09626    if (i->amaflags)
09627       tmp->amaflags = i->amaflags;
09628    i->subs[idx].owner = tmp;
09629    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09630    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09631       ast_string_field_set(tmp, call_forward, i->call_forward);
09632    }
09633    /* If we've been told "no ADSI" then enforce it */
09634    if (!i->adsi)
09635       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09636    if (!ast_strlen_zero(i->exten))
09637       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09638    if (!ast_strlen_zero(i->rdnis)) {
09639       tmp->redirecting.from.number.valid = 1;
09640       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09641    }
09642    if (!ast_strlen_zero(i->dnid)) {
09643       tmp->dialed.number.str = ast_strdup(i->dnid);
09644    }
09645 
09646    /* Don't use ast_set_callerid() here because it will
09647     * generate a needless NewCallerID event */
09648 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09649    if (!ast_strlen_zero(i->cid_ani)) {
09650       tmp->caller.ani.number.valid = 1;
09651       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09652    } else if (!ast_strlen_zero(i->cid_num)) {
09653       tmp->caller.ani.number.valid = 1;
09654       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09655    }
09656 #else
09657    if (!ast_strlen_zero(i->cid_num)) {
09658       tmp->caller.ani.number.valid = 1;
09659       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09660    }
09661 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09662    tmp->caller.id.name.presentation = i->callingpres;
09663    tmp->caller.id.number.presentation = i->callingpres;
09664    tmp->caller.id.number.plan = i->cid_ton;
09665    tmp->caller.ani2 = i->cid_ani2;
09666    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09667    /* clear the fake event in case we posted one before we had ast_channel */
09668    i->fake_event = 0;
09669    /* Assure there is no confmute on this channel */
09670    dahdi_confmute(i, 0);
09671    i->muting = 0;
09672    /* Configure the new channel jb */
09673    ast_jb_configure(tmp, &global_jbconf);
09674 
09675    /* Set initial device state */
09676    ast_copy_string(device_name, tmp->name, sizeof(device_name));
09677    dashptr = strrchr(device_name, '-');
09678    if (dashptr) {
09679       *dashptr = '\0';
09680    }
09681    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09682 
09683    for (v = i->vars ; v ; v = v->next)
09684       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09685 
09686    ast_module_ref(ast_module_info->self);
09687 
09688    dahdi_ami_channel_event(i, tmp);
09689    if (startpbx) {
09690 #ifdef HAVE_OPENR2
09691       if (i->mfcr2call) {
09692          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09693       }
09694 #endif
09695       if (ast_pbx_start(tmp)) {
09696          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09697          ast_hangup(tmp);
09698          return NULL;
09699       }
09700    }
09701    return tmp;
09702 }

static int dahdi_new_pri_nobch_channel ( struct sig_pri_span pri  )  [static]

Definition at line 13182 of file chan_dahdi.c.

References CHAN_PSEUDO, sig_pri_span::numchans, and sig_pri_span::pvts.

13183 {
13184    int pvt_idx;
13185    int res;
13186    unsigned idx;
13187    struct dahdi_pvt *pvt;
13188    struct sig_pri_chan *chan;
13189    struct dahdi_bufferinfo bi;
13190 
13191    static int nobch_channel = CHAN_PSEUDO;
13192 
13193    /* Find spot in the private pointer array for new interface. */
13194    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13195       if (!pri->pvts[pvt_idx]) {
13196          break;
13197       }
13198    }
13199    if (pri->numchans == pvt_idx) {
13200       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13201          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13202          return -1;
13203       }
13204 
13205       /* Add new spot to the private pointer array. */
13206       pri->pvts[pvt_idx] = NULL;
13207       ++pri->numchans;
13208    }
13209 
13210    pvt = ast_calloc(1, sizeof(*pvt));
13211    if (!pvt) {
13212       return -1;
13213    }
13214    pvt->cc_params = ast_cc_config_params_init();
13215    if (!pvt->cc_params) {
13216       ast_free(pvt);
13217       return -1;
13218    }
13219    ast_mutex_init(&pvt->lock);
13220    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13221       pvt->subs[idx].dfd = -1;
13222    }
13223    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13224    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13225    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13226    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13227 
13228    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13229    if (!chan) {
13230       destroy_dahdi_pvt(pvt);
13231       return -1;
13232    }
13233    chan->no_b_channel = 1;
13234 
13235    /*
13236     * Pseudo channel companding law.
13237     * Needed for outgoing call waiting calls.
13238     * XXX May need to make this determined by switchtype or user option.
13239     */
13240    pvt->law_default = DAHDI_LAW_ALAW;
13241 
13242    pvt->sig = pri->sig;
13243    pvt->outsigmod = -1;
13244    pvt->pri = pri;
13245    pvt->sig_pvt = chan;
13246    pri->pvts[pvt_idx] = chan;
13247 
13248    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13249    if (pvt->subs[SUB_REAL].dfd < 0) {
13250       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13251          strerror(errno));
13252       destroy_dahdi_pvt(pvt);
13253       return -1;
13254    }
13255    memset(&bi, 0, sizeof(bi));
13256    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13257    if (!res) {
13258       pvt->bufsize = bi.bufsize;
13259       bi.txbufpolicy = pvt->buf_policy;
13260       bi.rxbufpolicy = pvt->buf_policy;
13261       bi.numbufs = pvt->buf_no;
13262       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13263       if (res < 0) {
13264          ast_log(LOG_WARNING,
13265             "Unable to set buffer policy on no B channel interface: %s\n",
13266             strerror(errno));
13267       }
13268    } else
13269       ast_log(LOG_WARNING,
13270          "Unable to check buffer policy on no B channel interface: %s\n",
13271          strerror(errno));
13272 
13273    --nobch_channel;
13274    if (CHAN_PSEUDO < nobch_channel) {
13275       nobch_channel = CHAN_PSEUDO - 1;
13276    }
13277    pvt->channel = nobch_channel;
13278    pvt->span = pri->span;
13279    chan->channel = pvt->channel;
13280 
13281    dahdi_nobch_insert(pri, pvt);
13282 
13283    return pvt_idx;
13284 }

static void dahdi_nobch_extract ( struct sig_pri_span pri,
struct dahdi_pvt pvt 
) [static]

Definition at line 5583 of file chan_dahdi.c.

References DAHDI_IFLIST_NONE, dahdi_pvt::next, sig_pri_span::no_b_chan_end, sig_pri_span::no_b_chan_iflist, dahdi_pvt::prev, dahdi_pvt::pri, and dahdi_pvt::which_iflist.

Referenced by destroy_dahdi_pvt().

05584 {
05585    /* Extract from the forward chain. */
05586    if (pvt->prev) {
05587       pvt->prev->next = pvt->next;
05588    } else if (pri->no_b_chan_iflist == pvt) {
05589       /* Node is at the head of the list. */
05590       pri->no_b_chan_iflist = pvt->next;
05591    }
05592 
05593    /* Extract from the reverse chain. */
05594    if (pvt->next) {
05595       pvt->next->prev = pvt->prev;
05596    } else if (pri->no_b_chan_end == pvt) {
05597       /* Node is at the end of the list. */
05598       pri->no_b_chan_end = pvt->prev;
05599    }
05600 
05601    /* Node is no longer in the list. */
05602    pvt->which_iflist = DAHDI_IFLIST_NONE;
05603    pvt->prev = NULL;
05604    pvt->next = NULL;
05605 }

static void dahdi_nobch_insert ( struct sig_pri_span pri,
struct dahdi_pvt pvt 
) [static]

Definition at line 5530 of file chan_dahdi.c.

References dahdi_pvt::channel, DAHDI_IFLIST_NO_B_CHAN, dahdi_pvt::next, sig_pri_span::no_b_chan_end, sig_pri_span::no_b_chan_iflist, dahdi_pvt::prev, dahdi_pvt::pri, and dahdi_pvt::which_iflist.

05531 {
05532    struct dahdi_pvt *cur;
05533 
05534    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05535 
05536    /* Find place in middle of list for the new interface. */
05537    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05538       if (pvt->channel < cur->channel) {
05539          /* New interface goes before the current interface. */
05540          pvt->prev = cur->prev;
05541          pvt->next = cur;
05542          if (cur->prev) {
05543             /* Insert into the middle of the list. */
05544             cur->prev->next = pvt;
05545          } else {
05546             /* Insert at head of list. */
05547             pri->no_b_chan_iflist = pvt;
05548          }
05549          cur->prev = pvt;
05550          return;
05551       }
05552    }
05553 
05554    /* New interface goes onto the end of the list */
05555    pvt->prev = pri->no_b_chan_end;
05556    pvt->next = NULL;
05557    if (pri->no_b_chan_end) {
05558       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05559    }
05560    pri->no_b_chan_end = pvt;
05561    if (!pri->no_b_chan_iflist) {
05562       /* List was empty */
05563       pri->no_b_chan_iflist = pvt;
05564    }
05565 }

static int dahdi_open ( char *  fn  )  [static]

Definition at line 4250 of file chan_dahdi.c.

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

Referenced by alloc_sub(), and duplicate_pseudo().

04251 {
04252    int fd;
04253    int isnum;
04254    int chan = 0;
04255    int bs;
04256    int x;
04257    isnum = 1;
04258    for (x = 0; x < strlen(fn); x++) {
04259       if (!isdigit(fn[x])) {
04260          isnum = 0;
04261          break;
04262       }
04263    }
04264    if (isnum) {
04265       chan = atoi(fn);
04266       if (chan < 1) {
04267          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04268          return -1;
04269       }
04270       fn = "/dev/dahdi/channel";
04271    }
04272    fd = open(fn, O_RDWR | O_NONBLOCK);
04273    if (fd < 0) {
04274       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04275       return -1;
04276    }
04277    if (chan) {
04278       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04279          x = errno;
04280          close(fd);
04281          errno = x;
04282          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04283          return -1;
04284       }
04285    }
04286    bs = READ_SIZE;
04287    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04288       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04289       x = errno;
04290       close(fd);
04291       errno = x;
04292       return -1;
04293    }
04294    return fd;
04295 }

static void dahdi_pri_cc_agent_destructor ( struct ast_cc_agent agent  )  [static]

Definition at line 16530 of file chan_dahdi.c.

References ast_module_unref(), and sig_pri_cc_agent_destructor().

16531 {
16532    sig_pri_cc_agent_destructor(agent);
16533 
16534    ast_module_unref(ast_module_info->self);
16535 }

static int dahdi_pri_cc_agent_init ( struct ast_cc_agent agent,
struct ast_channel chan 
) [static]

Definition at line 16486 of file chan_dahdi.c.

References ast_assert, ast_module_ref(), ast_module_unref(), dahdi_sig_pri_lib_handles(), dahdi_pvt::sig, sig_pri_cc_agent_init(), dahdi_pvt::sig_pvt, ast_channel::tech, ast_channel::tech_pvt, and ast_channel_tech::type.

16487 {
16488    struct dahdi_pvt *pvt;
16489    struct sig_pri_chan *pvt_chan;
16490    int res;
16491 
16492    ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16493 
16494    pvt = chan->tech_pvt;
16495    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16496       pvt_chan = pvt->sig_pvt;
16497    } else {
16498       pvt_chan = NULL;
16499    }
16500    if (!pvt_chan) {
16501       return -1;
16502    }
16503 
16504    ast_module_ref(ast_module_info->self);
16505 
16506    res = sig_pri_cc_agent_init(agent, pvt_chan);
16507    if (res) {
16508       ast_module_unref(ast_module_info->self);
16509    }
16510    return res;
16511 }

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

Definition at line 14006 of file chan_dahdi.c.

References pris.

Referenced by load_module().

14007 {
14008    int x;
14009    int y;
14010    int dchan = -1;
14011    int span = -1;
14012    int dchancount = 0;
14013 
14014    if (pri) {
14015       for (x = 0; x < NUM_SPANS; x++) {
14016          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14017             if (pris[x].pri.dchans[y]) {
14018                dchancount++;
14019             }
14020 
14021             if (pris[x].pri.dchans[y] == pri) {
14022                dchan = y;
14023             }
14024          }
14025          if (dchan >= 0) {
14026             span = x;
14027             break;
14028          }
14029          dchancount = 0;
14030       }
14031       if (-1 < span) {
14032          if (1 < dchancount) {
14033             ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14034          } else {
14035             ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14036          }
14037       } else {
14038          ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14039       }
14040    } else {
14041       ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14042    }
14043 
14044    ast_mutex_lock(&pridebugfdlock);
14045 
14046    if (pridebugfd >= 0) {
14047       if (write(pridebugfd, s, strlen(s)) < 0) {
14048          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14049       }
14050    }
14051 
14052    ast_mutex_unlock(&pridebugfdlock);
14053 }

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

Definition at line 13955 of file chan_dahdi.c.

References pris.

Referenced by load_module().

13956 {
13957    int x;
13958    int y;
13959    int dchan = -1;
13960    int span = -1;
13961    int dchancount = 0;
13962 
13963    if (pri) {
13964       for (x = 0; x < NUM_SPANS; x++) {
13965          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13966             if (pris[x].pri.dchans[y]) {
13967                dchancount++;
13968             }
13969 
13970             if (pris[x].pri.dchans[y] == pri) {
13971                dchan = y;
13972             }
13973          }
13974          if (dchan >= 0) {
13975             span = x;
13976             break;
13977          }
13978          dchancount = 0;
13979       }
13980       if (-1 < span) {
13981          if (1 < dchancount) {
13982             ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
13983          } else {
13984             ast_verbose("PRI Span: %d %s", span + 1, s);
13985          }
13986       } else {
13987          ast_verbose("PRI Span: ? %s", s);
13988       }
13989    } else {
13990       ast_verbose("PRI Span: ? %s", s);
13991    }
13992 
13993    ast_mutex_lock(&pridebugfdlock);
13994 
13995    if (pridebugfd >= 0) {
13996       if (write(pridebugfd, s, strlen(s)) < 0) {
13997          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13998       }
13999    }
14000 
14001    ast_mutex_unlock(&pridebugfdlock);
14002 }

static void dahdi_pri_update_span_devstate ( struct sig_pri_span pri  )  [static]

Definition at line 3250 of file chan_dahdi.c.

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, ast_device_state(), AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_changed(), sig_pri_span::congestion_devstate, sig_pri_chan::inalarm, sig_pri_chan::no_b_channel, sig_pri_span::numchans, dahdi_pvt::pri, sig_pri_span::pvts, sig_pri_is_chan_available(), and sig_pri_span::span.

03251 {
03252    unsigned idx;
03253    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03254    unsigned in_use;     /* Number of B channels in use on the span. */
03255    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03256    enum ast_device_state new_state;
03257 
03258    /* Count the number of B channels and the number of B channels in use. */
03259    num_b_chans = 0;
03260    in_use = 0;
03261    in_alarm = 1;
03262    for (idx = pri->numchans; idx--;) {
03263       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03264          /* This is a B channel interface. */
03265          ++num_b_chans;
03266          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03267             ++in_use;
03268          }
03269          if (!pri->pvts[idx]->inalarm) {
03270             /* There is a channel that is not in alarm. */
03271             in_alarm = 0;
03272          }
03273       }
03274    }
03275 
03276    /* Update the span congestion device state and report any change. */
03277    if (in_alarm) {
03278       new_state = AST_DEVICE_UNAVAILABLE;
03279    } else {
03280       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03281    }
03282    if (pri->congestion_devstate != new_state) {
03283       pri->congestion_devstate = new_state;
03284       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03285    }
03286 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03287    /* Update the span threshold device state and report any change. */
03288    if (in_alarm) {
03289       new_state = AST_DEVICE_UNAVAILABLE;
03290    } else if (!in_use) {
03291       new_state = AST_DEVICE_NOT_INUSE;
03292    } else if (!pri->user_busy_threshold) {
03293       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03294    } else {
03295       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03296          : AST_DEVICE_BUSY;
03297    }
03298    if (pri->threshold_devstate != new_state) {
03299       pri->threshold_devstate = new_state;
03300       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03301    }
03302 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03303 }

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

Definition at line 6605 of file chan_dahdi.c.

References ast_copy_string(), ast_debug, AST_OPTION_CC_AGENT_TYPE, AST_OPTION_DIGIT_DETECT, AST_OPTION_FAX_DETECT, dahdi_pri_cc_type, dahdi_sig_pri_lib_handles(), DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, errno, dahdi_pvt::ignoredtmf, ast_channel::name, dahdi_pvt::sig, and ast_channel::tech_pvt.

06606 {
06607    char *cp;
06608    struct dahdi_pvt *p = chan->tech_pvt;
06609 
06610    /* all supported options require data */
06611    if (!p || !data || (*datalen < 1)) {
06612       errno = EINVAL;
06613       return -1;
06614    }
06615 
06616    switch (option) {
06617    case AST_OPTION_DIGIT_DETECT:
06618       cp = (char *) data;
06619       *cp = p->ignoredtmf ? 0 : 1;
06620       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06621       break;
06622    case AST_OPTION_FAX_DETECT:
06623       cp = (char *) data;
06624       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06625       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06626       break;
06627    case AST_OPTION_CC_AGENT_TYPE:
06628 #if defined(HAVE_PRI)
06629 #if defined(HAVE_PRI_CCSS)
06630       if (dahdi_sig_pri_lib_handles(p->sig)) {
06631          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06632          break;
06633       }
06634 #endif   /* defined(HAVE_PRI_CCSS) */
06635 #endif   /* defined(HAVE_PRI) */
06636       return -1;
06637    default:
06638       return -1;
06639    }
06640 
06641    errno = 0;
06642 
06643    return 0;
06644 }

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

Definition at line 3744 of file chan_dahdi.c.

References ast_channel_trylock, ast_channel_unlock, ast_queue_frame(), DEADLOCK_AVOIDANCE, f, dahdi_pvt::lock, and dahdi_pvt::owner.

Referenced by action_dahdidialoffhook().

03745 {
03746    for (;;) {
03747       if (p->owner) {
03748          if (ast_channel_trylock(p->owner)) {
03749             DEADLOCK_AVOIDANCE(&p->lock);
03750          } else {
03751             ast_queue_frame(p->owner, f);
03752             ast_channel_unlock(p->owner);
03753             break;
03754          }
03755       } else
03756          break;
03757    }
03758 }

static int16_t dahdi_r2_alaw_to_linear ( uint8_t  sample  )  [inline, static]

Definition at line 4205 of file chan_dahdi.c.

References AST_ALAW.

04206 {
04207    return AST_ALAW(sample);
04208 }

static int dahdi_r2_answer ( struct dahdi_pvt p  )  [static]

Definition at line 3774 of file chan_dahdi.c.

References ast_true(), dahdi_pvt::owner, pbx_builtin_getvar_helper(), and dahdi_pvt::r2chan.

Referenced by dahdi_answer(), and dahdi_r2_on_call_accepted().

03775 {
03776    int res = 0;
03777    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03778    * and does not has support for openr2_chan_answer_call_with_mode
03779    *  */
03780 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03781    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03782    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03783    if (!double_answer) {
03784       /* this still can result in double answer if the channel context
03785       * was configured that way */
03786       res = openr2_chan_answer_call(p->r2chan);
03787    } else if (wants_double_answer) {
03788       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03789    } else {
03790       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03791    }
03792 #else
03793    res = openr2_chan_answer_call(p->r2chan);
03794 #endif
03795    return res;
03796 }

static int dahdi_r2_cause_to_ast_cause ( openr2_call_disconnect_cause_t  cause  )  [static]

Definition at line 4015 of file chan_dahdi.c.

References AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_NOTDEFINED, and AST_CAUSE_UNREGISTERED.

Referenced by dahdi_r2_on_call_disconnect().

04016 {
04017    switch (cause) {
04018    case OR2_CAUSE_BUSY_NUMBER:
04019       return AST_CAUSE_BUSY;
04020    case OR2_CAUSE_NETWORK_CONGESTION:
04021       return AST_CAUSE_CONGESTION;
04022    case OR2_CAUSE_OUT_OF_ORDER:
04023       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04024    case OR2_CAUSE_UNALLOCATED_NUMBER:
04025       return AST_CAUSE_UNREGISTERED;
04026    case OR2_CAUSE_NO_ANSWER:
04027       return AST_CAUSE_NO_ANSWER;
04028    case OR2_CAUSE_NORMAL_CLEARING:
04029       return AST_CAUSE_NORMAL_CLEARING;
04030    case OR2_CAUSE_UNSPECIFIED:
04031    default:
04032       return AST_CAUSE_NOTDEFINED;
04033    }
04034 }

static void dahdi_r2_destroy_links ( void   )  [static]

Definition at line 12014 of file chan_dahdi.c.

References ast_free, AST_PTHREADT_NULL, r2links, and r2links_count.

Referenced by __unload_module(), and dahdi_restart().

12015 {
12016    int i = 0;
12017    if (!r2links) {
12018       return;
12019    }
12020    for (; i < r2links_count; i++) {
12021       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12022          pthread_cancel(r2links[i]->r2master);
12023          pthread_join(r2links[i]->r2master, NULL);
12024          openr2_context_delete(r2links[i]->protocol_context);
12025       }
12026       ast_free(r2links[i]);
12027    }
12028    ast_free(r2links);
12029    r2links = NULL;
12030    r2links_count = 0;
12031 }

static void dahdi_r2_disconnect_call ( struct dahdi_pvt p,
openr2_call_disconnect_cause_t  cause 
) [static]

Definition at line 3883 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, dahdi_pvt::lock, LOG_NOTICE, dahdi_pvt::mfcr2call, and dahdi_pvt::r2chan.

Referenced by dahdi_hangup(), dahdi_r2_on_call_accepted(), dahdi_r2_on_call_disconnect(), and dahdi_r2_on_call_offered().

03884 {
03885    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03886       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03887          p->channel, openr2_proto_get_disconnect_string(cause));
03888       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
03889       openr2_chan_set_idle(p->r2chan);
03890       ast_mutex_lock(&p->lock);
03891       p->mfcr2call = 0;
03892       ast_mutex_unlock(&p->lock);
03893    }
03894 }

static openr2_calling_party_category_t dahdi_r2_get_channel_category ( struct ast_channel c  )  [static]

Definition at line 3801 of file chan_dahdi.c.

References ast_debug, ast_log(), ast_strlen_zero(), LOG_WARNING, dahdi_pvt::mfcr2_category, ast_channel::name, pbx_builtin_getvar_helper(), and ast_channel::tech_pvt.

Referenced by dahdi_call().

03802 {
03803    openr2_calling_party_category_t cat;
03804    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03805    struct dahdi_pvt *p = c->tech_pvt;
03806    if (ast_strlen_zero(catstr)) {
03807       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03808             c->name, openr2_proto_get_category_string(p->mfcr2_category));
03809       return p->mfcr2_category;
03810    }
03811    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03812       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03813             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03814       return p->mfcr2_category;
03815    }
03816    ast_debug(1, "Using category %s\n", catstr);
03817    return cat;
03818 }

static struct dahdi_mfcr2* dahdi_r2_get_link ( void   )  [static]

Definition at line 12034 of file chan_dahdi.c.

References ast_calloc, ast_free, ast_log(), AST_PTHREADT_NULL, ast_realloc, LOG_DEBUG, LOG_ERROR, dahdi_mfcr2::monitored_count, R2_LINK_CAPACITY, r2links, r2links_count, and dahdi_mfcr2::r2master.

12035 {
12036    struct dahdi_mfcr2 *new_r2link = NULL;
12037    struct dahdi_mfcr2 **new_r2links = NULL;
12038    /* this function is called just when starting up and no monitor threads have been launched,
12039       no need to lock monitored_count member */
12040    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12041       new_r2link = ast_calloc(1, sizeof(**r2links));
12042       if (!new_r2link) {
12043          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12044          return NULL;
12045       }
12046       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12047       if (!new_r2links) {
12048          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12049          ast_free(new_r2link);
12050          return NULL;
12051       }
12052       r2links = new_r2links;
12053       new_r2link->r2master = AST_PTHREADT_NULL;
12054       r2links[r2links_count] = new_r2link;
12055       r2links_count++;
12056       ast_log(LOG_DEBUG, "Created new R2 link!\n");
12057    }
12058    return r2links[r2links_count - 1];
12059 }

static uint8_t dahdi_r2_linear_to_alaw ( int  sample  )  [inline, static]

Definition at line 4210 of file chan_dahdi.c.

References AST_LIN2A.

04211 {
04212    return AST_LIN2A(sample);
04213 }

static void dahdi_r2_on_ani_digit_received ( openr2_chan_t *  r2chan,
char  digit 
) [static]

Definition at line 4169 of file chan_dahdi.c.

References dahdi_pvt::cid_name, dahdi_pvt::cid_num, and dahdi_pvt::mfcr2_ani_index.

04170 {
04171    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04172    p->cid_num[p->mfcr2_ani_index] = digit;
04173    p->cid_name[p->mfcr2_ani_index] = digit;
04174    p->mfcr2_ani_index++;
04175    p->cid_num[p->mfcr2_ani_index] = 0;
04176    p->cid_name[p->mfcr2_ani_index] = 0;
04177 }

static void dahdi_r2_on_billing_pulse_received ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4179 of file chan_dahdi.c.

References ast_verbose.

04180 {
04181    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04182 }

static void dahdi_r2_on_call_accepted ( openr2_chan_t *  r2chan,
openr2_call_mode_t  mode 
) [static]

Definition at line 3961 of file chan_dahdi.c.

References ast_log(), AST_STATE_RING, ast_verbose, dahdi_pvt::channel, dahdi_enable_ec(), dahdi_new(), dahdi_r2_answer(), dahdi_r2_disconnect_call(), dahdi_pvt::dialing, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_answer_pending, dahdi_pvt::mfcr2_call_accepted, dahdi_subchannel::needringing, SUB_REAL, and dahdi_pvt::subs.

03962 {
03963    struct dahdi_pvt *p = NULL;
03964    struct ast_channel *c = NULL;
03965    p = openr2_chan_get_client_data(r2chan);
03966    dahdi_enable_ec(p);
03967    p->mfcr2_call_accepted = 1;
03968    /* if it's an incoming call ... */
03969    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
03970       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
03971       /* If accept on offer is not set, it means at this point the PBX thread is already
03972          launched (was launched in the 'on call offered' handler) and therefore this callback
03973          is being executed already in the PBX thread rather than the monitor thread, don't launch
03974          any other thread, just disable the openr2 reading and answer the call if needed */
03975       if (!p->mfcr2_accept_on_offer) {
03976          openr2_chan_disable_read(r2chan);
03977          if (p->mfcr2_answer_pending) {
03978             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
03979             dahdi_r2_answer(p);
03980          }
03981          return;
03982       }
03983       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03984       if (c) {
03985          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
03986             library to forget about it */
03987          openr2_chan_disable_read(r2chan);
03988          return;
03989       }
03990       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03991       /* failed to create the channel, bail out and report it as an out of order line */
03992       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03993       return;
03994    }
03995    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
03996    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
03997    p->subs[SUB_REAL].needringing = 1;
03998    p->dialing = 0;
03999    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
04000    openr2_chan_disable_read(r2chan);
04001 }

static void dahdi_r2_on_call_answered ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4003 of file chan_dahdi.c.

References ast_verbose, dahdi_subchannel::needanswer, SUB_REAL, and dahdi_pvt::subs.

04004 {
04005    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04006    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04007    p->subs[SUB_REAL].needanswer = 1;
04008 }

static void dahdi_r2_on_call_disconnect ( openr2_chan_t *  r2chan,
openr2_call_disconnect_cause_t  cause 
) [static]

Definition at line 4036 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, ast_mutex_lock, ast_mutex_unlock, ast_queue_hangup_with_cause(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_verbose, dahdi_r2_cause_to_ast_cause(), dahdi_r2_disconnect_call(), dahdi_pvt::lock, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_pvt::owner, SUB_REAL, and dahdi_pvt::subs.

04037 {
04038    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04039    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04040    ast_mutex_lock(&p->lock);
04041    if (!p->owner) {
04042       ast_mutex_unlock(&p->lock);
04043       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04044       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04045       return;
04046    }
04047    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04048       be done in dahdi_hangup */
04049    if (p->owner->_state == AST_STATE_UP) {
04050       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04051       ast_mutex_unlock(&p->lock);
04052    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04053       /* being the forward side we must report what happened to the call to whoever requested it */
04054       switch (cause) {
04055       case OR2_CAUSE_BUSY_NUMBER:
04056          p->subs[SUB_REAL].needbusy = 1;
04057          break;
04058       case OR2_CAUSE_NETWORK_CONGESTION:
04059       case OR2_CAUSE_OUT_OF_ORDER:
04060       case OR2_CAUSE_UNALLOCATED_NUMBER:
04061       case OR2_CAUSE_NO_ANSWER:
04062       case OR2_CAUSE_UNSPECIFIED:
04063       case OR2_CAUSE_NORMAL_CLEARING:
04064          p->subs[SUB_REAL].needcongestion = 1;
04065          break;
04066       default:
04067          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04068       }
04069       ast_mutex_unlock(&p->lock);
04070    } else {
04071       ast_mutex_unlock(&p->lock);
04072       /* being the backward side and not UP yet, we only need to request hangup */
04073       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04074       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04075    }
04076 }

static void dahdi_r2_on_call_end ( openr2_chan_t *  r2chan  )  [static]

Definition at line 3951 of file chan_dahdi.c.

References ast_mutex_lock, ast_mutex_unlock, ast_verbose, dahdi_pvt::channel, dahdi_pvt::lock, and dahdi_pvt::mfcr2call.

03952 {
03953    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03954    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
03955    ast_mutex_lock(&p->lock);
03956    p->mfcr2call = 0;
03957    ast_mutex_unlock(&p->lock);
03958 }

static void dahdi_r2_on_call_init ( openr2_chan_t *  r2chan  )  [static]

Definition at line 3820 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::exten, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mfcr2_ani_index, dahdi_pvt::mfcr2_answer_pending, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_dnis_matched, dahdi_pvt::mfcr2call, and dahdi_pvt::rdnis.

03821 {
03822    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03823    ast_mutex_lock(&p->lock);
03824    if (p->mfcr2call) {
03825       ast_mutex_unlock(&p->lock);
03826       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03827          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03828          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03829          the other end will see our seize as a forced release and drop the call, we will see an invalid
03830          pattern that will be seen and treated as protocol error. */
03831       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03832       return;
03833    }
03834    p->mfcr2call = 1;
03835    /* better safe than sorry ... */
03836    p->cid_name[0] = '\0';
03837    p->cid_num[0] = '\0';
03838    p->cid_subaddr[0] = '\0';
03839    p->rdnis[0] = '\0';
03840    p->exten[0] = '\0';
03841    p->mfcr2_ani_index = '\0';
03842    p->mfcr2_dnis_index = '\0';
03843    p->mfcr2_dnis_matched = 0;
03844    p->mfcr2_answer_pending = 0;
03845    p->mfcr2_call_accepted = 0;
03846    ast_mutex_unlock(&p->lock);
03847    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03848 }

static void dahdi_r2_on_call_offered ( openr2_chan_t *  r2chan,
const char *  ani,
const char *  dnis,
openr2_calling_party_category_t  category 
) [static]

Definition at line 3896 of file chan_dahdi.c.

References ast_exists_extension(), ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_STATE_RING, ast_verbose, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::context, dahdi_new(), dahdi_r2_disconnect_call(), dahdi_pvt::exten, dahdi_pvt::immediate, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_allow_collect_calls, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::mfcr2_recvd_category, SUB_REAL, and dahdi_pvt::use_callerid.

03897 {
03898    struct dahdi_pvt *p;
03899    struct ast_channel *c;
03900    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03901          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03902          openr2_proto_get_category_string(category));
03903    p = openr2_chan_get_client_data(r2chan);
03904    /* if collect calls are not allowed and this is a collect call, reject it! */
03905    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03906       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03907       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03908       return;
03909    }
03910    ast_mutex_lock(&p->lock);
03911    p->mfcr2_recvd_category = category;
03912    /* if we're not supposed to use CID, clear whatever we have */
03913    if (!p->use_callerid) {
03914       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03915       p->cid_num[0] = 0;
03916       p->cid_name[0] = 0;
03917    }
03918    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
03919    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03920       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03921       p->exten[0] = 's';
03922       p->exten[1] = 0;
03923    }
03924    ast_mutex_unlock(&p->lock);
03925    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03926       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03927             p->channel, p->exten, p->context);
03928       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03929       return;
03930    }
03931    if (!p->mfcr2_accept_on_offer) {
03932       /* The user wants us to start the PBX thread right away without accepting the call first */
03933       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03934       if (c) {
03935          /* Done here, don't disable reading now since we still need to generate MF tones to accept
03936             the call or reject it and detect the tone off condition of the other end, all of this
03937             will be done in the PBX thread now */
03938          return;
03939       }
03940       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03941       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03942    } else if (p->mfcr2_charge_calls) {
03943       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03944       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03945    } else {
03946       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
03947       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
03948    }
03949 }

static void dahdi_r2_on_call_read ( openr2_chan_t *  r2chan,
const unsigned char *  buf,
int  buflen 
) [static]

Definition at line 4010 of file chan_dahdi.c.

04011 {
04012    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
04013 }

static void dahdi_r2_on_chan_log ( openr2_chan_t *  r2chan,
openr2_log_level_t  level,
const char *  fmt,
va_list  ap 
) [static]

Definition at line 4137 of file chan_dahdi.c.

References CHAN_TAG, and dahdi_r2_write_log().

04138 {
04139 #define CHAN_TAG "Chan "
04140    char logmsg[256];
04141    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04142    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04143    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04144    dahdi_r2_write_log(level, completemsg);
04145 }

static void dahdi_r2_on_context_log ( openr2_context_t *  r2context,
openr2_log_level_t  level,
const char *  fmt,
va_list  ap 
) [static]

Definition at line 4124 of file chan_dahdi.c.

References CONTEXT_TAG, and dahdi_r2_write_log().

04125 {
04126 #define CONTEXT_TAG "Context - "
04127    char logmsg[256];
04128    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04129    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04130    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04131    dahdi_r2_write_log(level, completemsg);
04132 #undef CONTEXT_TAG
04133 }

static int dahdi_r2_on_dnis_digit_received ( openr2_chan_t *  r2chan,
char  digit 
) [static]

Definition at line 4147 of file chan_dahdi.c.

References ast_exists_extension(), ast_matchmore_extension(), dahdi_pvt::cid_num, dahdi_pvt::context, dahdi_pvt::exten, dahdi_pvt::immediate, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_dnis_matched, and dahdi_pvt::rdnis.

04148 {
04149    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04150    /* if 'immediate' is set, let's stop requesting DNIS */
04151    if (p->immediate) {
04152       return 0;
04153    }
04154    p->exten[p->mfcr2_dnis_index] = digit;
04155    p->rdnis[p->mfcr2_dnis_index] = digit;
04156    p->mfcr2_dnis_index++;
04157    p->exten[p->mfcr2_dnis_index] = 0;
04158    p->rdnis[p->mfcr2_dnis_index] = 0;
04159    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04160    if ((p->mfcr2_dnis_matched ||
04161        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04162        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04163       return 0;
04164    }
04165    /* otherwise keep going */
04166    return 1;
04167 }

static void dahdi_r2_on_hardware_alarm ( openr2_chan_t *  r2chan,
int  alarm 
) [static]

Definition at line 3850 of file chan_dahdi.c.

References ast_mutex_lock, ast_mutex_unlock, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::inalarm, and dahdi_pvt::lock.

03851 {
03852    int res;
03853    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03854    ast_mutex_lock(&p->lock);
03855    p->inalarm = alarm ? 1 : 0;
03856    if (p->inalarm) {
03857       res = get_alarms(p);
03858       handle_alarms(p, res);
03859    } else {
03860       handle_clear_alarms(p);
03861    }
03862    ast_mutex_unlock(&p->lock);
03863 }

static void dahdi_r2_on_line_blocked ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4104 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::lock, LOG_NOTICE, and dahdi_pvt::remotelyblocked.

04105 {
04106    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04107    ast_mutex_lock(&p->lock);
04108    p->remotelyblocked = 1;
04109    ast_mutex_unlock(&p->lock);
04110    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04111 }

static void dahdi_r2_on_line_idle ( openr2_chan_t *  r2chan  )  [static]

Definition at line 4113 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::lock, LOG_NOTICE, and dahdi_pvt::remotelyblocked.

04114 {
04115    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04116    ast_mutex_lock(&p->lock);
04117    p->remotelyblocked = 0;
04118    ast_mutex_unlock(&p->lock);
04119    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04120 }

static void dahdi_r2_on_os_error ( openr2_chan_t *  r2chan,
int  errorcode 
) [static]

Definition at line 3865 of file chan_dahdi.c.

References ast_log(), and LOG_ERROR.

03866 {
03867    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03868 }

static void dahdi_r2_on_protocol_error ( openr2_chan_t *  r2chan,
openr2_protocol_error_t  reason 
) [static]

Definition at line 3870 of file chan_dahdi.c.

References ast_channel::_softhangup, AST_CAUSE_PROTOCOL_ERROR, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_SOFTHANGUP_DEV, ast_channel::hangupcause, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mfcr2call, and dahdi_pvt::owner.

03871 {
03872    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03873    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03874    if (p->owner) {
03875       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03876       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03877    }
03878    ast_mutex_lock(&p->lock);
03879    p->mfcr2call = 0;
03880    ast_mutex_unlock(&p->lock);
03881 }

static int dahdi_r2_set_context ( struct dahdi_mfcr2 r2_link,
const struct dahdi_chan_conf conf 
) [static]

Definition at line 12061 of file chan_dahdi.c.

References ast_config_AST_LOG_DIR, ast_log(), ast_strlen_zero(), dahdi_mfcr2_conf::double_answer, dahdi_mfcr2_conf::get_ani_first, dahdi_mfcr2_conf::immediate_accept, LOG_ERROR, dahdi_mfcr2_conf::logdir, dahdi_mfcr2_conf::loglevel, dahdi_mfcr2_conf::max_ani, dahdi_mfcr2_conf::max_dnis, dahdi_mfcr2_conf::metering_pulse_timeout, dahdi_mfcr2_conf::mfback_timeout, dahdi_chan_conf::mfcr2, dahdi_mfcr2::monitored_count, dahdi_mfcr2::protocol_context, dahdi_mfcr2_conf::r2proto_file, and dahdi_mfcr2_conf::variant.

12062 {
12063    char tmplogdir[] = "/tmp";
12064    char logdir[OR2_MAX_PATH];
12065    int threshold = 0;
12066    int snres = 0;
12067    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12068          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12069          conf->mfcr2.max_dnis);
12070    if (!r2_link->protocol_context) {
12071       return -1;
12072    }
12073    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12074    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12075 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12076    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12077 #endif
12078    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12079    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12080    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12081    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12082    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12083    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12084       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12085          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12086       }
12087    } else {
12088       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12089       if (snres >= sizeof(logdir)) {
12090          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12091          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12092             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12093          }
12094       } else {
12095          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12096             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12097          }
12098       }
12099    }
12100    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12101       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12102          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12103       }
12104    }
12105    r2_link->monitored_count = 0;
12106    return 0;
12107 }

static void dahdi_r2_write_log ( openr2_log_level_t  level,
char *  logmessage 
) [static]

Definition at line 4078 of file chan_dahdi.c.

References ast_log(), ast_verbose, LOG_DEBUG, LOG_ERROR, and LOG_WARNING.

Referenced by dahdi_r2_on_chan_log(), and dahdi_r2_on_context_log().

04079 {
04080    switch (level) {
04081    case OR2_LOG_NOTICE:
04082       ast_verbose("%s", logmessage);
04083       break;
04084    case OR2_LOG_WARNING:
04085       ast_log(LOG_WARNING, "%s", logmessage);
04086       break;
04087    case OR2_LOG_ERROR:
04088       ast_log(LOG_ERROR, "%s", logmessage);
04089       break;
04090    case OR2_LOG_STACK_TRACE:
04091    case OR2_LOG_MF_TRACE:
04092    case OR2_LOG_CAS_TRACE:
04093    case OR2_LOG_DEBUG:
04094    case OR2_LOG_EX_DEBUG:
04095       ast_log(LOG_DEBUG, "%s", logmessage);
04096       break;
04097    default:
04098       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04099       ast_log(LOG_DEBUG, "%s", logmessage);
04100       break;
04101    }
04102 }

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

Definition at line 8800 of file chan_dahdi.c.

References __dahdi_exception(), ast_channel::_state, analog_exception(), analog_handle_dtmf(), analog_lib_handles(), ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, 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_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, 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_queue_frame(), 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::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidspill, ast_frame_subclass::codec, dahdi_callwait(), dahdi_confmute(), dahdi_get_index, dahdi_handle_dtmf(), DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_setlinear(), dahdi_sig_pri_lib_handles(), 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, f, dahdi_pvt::fake_event, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, ast_frame::mallocd, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_progress, mute, dahdi_pvt::muting, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_pvt::outgoing, sig_pri_span::overlapdial, dahdi_pvt::owner, dahdi_pvt::pri, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, ast_channel::rawreadformat, READ_SIZE, restore_conference(), dahdi_pvt::ringt, ast_frame::samples, send_callerid(), dahdi_pvt::sig, SIG_PRI_CALL_LEVEL_PROCEEDING, dahdi_pvt::sig_pvt, 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.

08801 {
08802    struct dahdi_pvt *p;
08803    int res;
08804    int idx;
08805    void *readbuf;
08806    struct ast_frame *f;
08807 
08808    /*
08809     * For analog channels, we must do deadlock avoidance because
08810     * analog ports can have more than one Asterisk channel using
08811     * the same private structure.
08812     */
08813    p = ast->tech_pvt;
08814    while (ast_mutex_trylock(&p->lock)) {
08815       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08816 
08817       /*
08818        * For PRI channels, we must refresh the private pointer because
08819        * the call could move to another B channel while the Asterisk
08820        * channel is unlocked.
08821        */
08822       p = ast->tech_pvt;
08823    }
08824 
08825    idx = dahdi_get_index(ast, p, 0);
08826 
08827    /* Hang up if we don't really exist */
08828    if (idx < 0)   {
08829       ast_log(LOG_WARNING, "We don't exist?\n");
08830       ast_mutex_unlock(&p->lock);
08831       return NULL;
08832    }
08833 
08834    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08835       ast_mutex_unlock(&p->lock);
08836       return NULL;
08837    }
08838 
08839    p->subs[idx].f.frametype = AST_FRAME_NULL;
08840    p->subs[idx].f.datalen = 0;
08841    p->subs[idx].f.samples = 0;
08842    p->subs[idx].f.mallocd = 0;
08843    p->subs[idx].f.offset = 0;
08844    p->subs[idx].f.subclass.integer = 0;
08845    p->subs[idx].f.delivery = ast_tv(0,0);
08846    p->subs[idx].f.src = "dahdi_read";
08847    p->subs[idx].f.data.ptr = NULL;
08848 
08849    /* make sure it sends initial key state as first frame */
08850    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08851    {
08852       struct dahdi_params ps;
08853 
08854       memset(&ps, 0, sizeof(ps));
08855       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08856          ast_mutex_unlock(&p->lock);
08857          return NULL;
08858       }
08859       p->firstradio = 1;
08860       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08861       if (ps.rxisoffhook)
08862       {
08863          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08864       }
08865       else
08866       {
08867          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08868       }
08869       ast_mutex_unlock(&p->lock);
08870       return &p->subs[idx].f;
08871    }
08872    if (p->ringt > 0) {
08873       if (!(--p->ringt)) {
08874          ast_mutex_unlock(&p->lock);
08875          return NULL;
08876       }
08877    }
08878 
08879 #ifdef HAVE_OPENR2
08880    if (p->mfcr2) {
08881       openr2_chan_process_event(p->r2chan);
08882       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08883          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
08884          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
08885           * now enqueue a progress frame to bridge the media up */
08886          if (p->mfcr2_call_accepted &&
08887              !p->mfcr2_progress && 
08888              ast->_state == AST_STATE_RINGING) {
08889             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
08890             ast_queue_frame(p->owner, &f);
08891             p->mfcr2_progress = 1;
08892          }
08893       }
08894    }
08895 #endif
08896 
08897    if (p->subs[idx].needringing) {
08898       /* Send ringing frame if requested */
08899       p->subs[idx].needringing = 0;
08900       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08901       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
08902       ast_setstate(ast, AST_STATE_RINGING);
08903       ast_mutex_unlock(&p->lock);
08904       return &p->subs[idx].f;
08905    }
08906 
08907    if (p->subs[idx].needbusy) {
08908       /* Send busy frame if requested */
08909       p->subs[idx].needbusy = 0;
08910       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08911       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
08912       ast_mutex_unlock(&p->lock);
08913       return &p->subs[idx].f;
08914    }
08915 
08916    if (p->subs[idx].needcongestion) {
08917       /* Send congestion frame if requested */
08918       p->subs[idx].needcongestion = 0;
08919       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08920       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
08921       ast_mutex_unlock(&p->lock);
08922       return &p->subs[idx].f;
08923    }
08924 
08925    if (p->subs[idx].needanswer) {
08926       /* Send answer frame if requested */
08927       p->subs[idx].needanswer = 0;
08928       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08929       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08930       ast_mutex_unlock(&p->lock);
08931       return &p->subs[idx].f;
08932    }
08933 #ifdef HAVE_OPENR2
08934    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
08935       /* openr2 took care of reading and handling any event
08936         (needanswer, needbusy etc), if we continue we will read()
08937         twice, lets just return a null frame. This should only
08938         happen when openr2 is dialing out */
08939       ast_mutex_unlock(&p->lock);
08940       return &ast_null_frame;
08941    }
08942 #endif
08943 
08944    if (p->subs[idx].needflash) {
08945       /* Send answer frame if requested */
08946       p->subs[idx].needflash = 0;
08947       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08948       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
08949       ast_mutex_unlock(&p->lock);
08950       return &p->subs[idx].f;
08951    }
08952 
08953    if (p->subs[idx].needhold) {
08954       /* Send answer frame if requested */
08955       p->subs[idx].needhold = 0;
08956       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08957       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
08958       ast_mutex_unlock(&p->lock);
08959       ast_debug(1, "Sending hold on '%s'\n", ast->name);
08960       return &p->subs[idx].f;
08961    }
08962 
08963    if (p->subs[idx].needunhold) {
08964       /* Send answer frame if requested */
08965       p->subs[idx].needunhold = 0;
08966       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08967       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
08968       ast_mutex_unlock(&p->lock);
08969       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
08970       return &p->subs[idx].f;
08971    }
08972 
08973    /*
08974     * If we have a fake_event, fake an exception to handle it only
08975     * if this channel owns the private.
08976     */
08977    if (p->fake_event && p->owner == ast) {
08978       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08979          struct analog_pvt *analog_p = p->sig_pvt;
08980 
08981          f = analog_exception(analog_p, ast);
08982       } else {
08983          f = __dahdi_exception(ast);
08984       }
08985       ast_mutex_unlock(&p->lock);
08986       return f;
08987    }
08988 
08989    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
08990       if (!p->subs[idx].linear) {
08991          p->subs[idx].linear = 1;
08992          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08993          if (res)
08994             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
08995       }
08996    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
08997       (ast->rawreadformat == AST_FORMAT_ALAW)) {
08998       if (p->subs[idx].linear) {
08999          p->subs[idx].linear = 0;
09000          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09001          if (res)
09002             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09003       }
09004    } else {
09005       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09006       ast_mutex_unlock(&p->lock);
09007       return NULL;
09008    }
09009    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09010    CHECK_BLOCKING(ast);
09011    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09012    ast_clear_flag(ast, AST_FLAG_BLOCKING);
09013    /* Check for hangup */
09014    if (res < 0) {
09015       f = NULL;
09016       if (res == -1) {
09017          if (errno == EAGAIN) {
09018             /* Return "NULL" frame if there is nobody there */
09019             ast_mutex_unlock(&p->lock);
09020             return &p->subs[idx].f;
09021          } else if (errno == ELAST) {
09022             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09023                struct analog_pvt *analog_p = p->sig_pvt;
09024                f = analog_exception(analog_p, ast);
09025             } else {
09026                f = __dahdi_exception(ast);
09027             }
09028          } else
09029             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09030       }
09031       ast_mutex_unlock(&p->lock);
09032       return f;
09033    }
09034    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09035       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09036       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09037          struct analog_pvt *analog_p = p->sig_pvt;
09038          f = analog_exception(analog_p, ast);
09039       } else {
09040          f = __dahdi_exception(ast);
09041       }
09042       ast_mutex_unlock(&p->lock);
09043       return f;
09044    }
09045    if (p->tdd) { /* if in TDD mode, see if we receive that */
09046       int c;
09047 
09048       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09049       if (c < 0) {
09050          ast_debug(1,"tdd_feed failed\n");
09051          ast_mutex_unlock(&p->lock);
09052          return NULL;
09053       }
09054       if (c) { /* if a char to return */
09055          p->subs[idx].f.subclass.integer = 0;
09056          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09057          p->subs[idx].f.mallocd = 0;
09058          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09059          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09060          p->subs[idx].f.datalen = 1;
09061          *((char *) p->subs[idx].f.data.ptr) = c;
09062          ast_mutex_unlock(&p->lock);
09063          return &p->subs[idx].f;
09064       }
09065    }
09066    if (idx == SUB_REAL) {
09067       /* Ensure the CW timers decrement only on a single subchannel */
09068       if (p->cidcwexpire) {
09069          if (!--p->cidcwexpire) {
09070             /* Expired CID/CW */
09071             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09072             restore_conference(p);
09073          }
09074       }
09075       if (p->cid_suppress_expire) {
09076          --p->cid_suppress_expire;
09077       }
09078       if (p->callwaitingrepeat) {
09079          if (!--p->callwaitingrepeat) {
09080             /* Expired, Repeat callwaiting tone */
09081             ++p->callwaitrings;
09082             dahdi_callwait(ast);
09083          }
09084       }
09085    }
09086    if (p->subs[idx].linear) {
09087       p->subs[idx].f.datalen = READ_SIZE * 2;
09088    } else
09089       p->subs[idx].f.datalen = READ_SIZE;
09090 
09091    /* Handle CallerID Transmission */
09092    if ((p->owner == ast) && p->cidspill) {
09093       send_callerid(p);
09094    }
09095 
09096    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09097    p->subs[idx].f.subclass.codec = ast->rawreadformat;
09098    p->subs[idx].f.samples = READ_SIZE;
09099    p->subs[idx].f.mallocd = 0;
09100    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09101    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09102 #if 0
09103    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09104 #endif
09105    if (p->dialing ||  p->radio || /* Transmitting something */
09106       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09107       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09108       ) {
09109       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09110          don't send anything */
09111       p->subs[idx].f.frametype = AST_FRAME_NULL;
09112       p->subs[idx].f.subclass.integer = 0;
09113       p->subs[idx].f.samples = 0;
09114       p->subs[idx].f.mallocd = 0;
09115       p->subs[idx].f.offset = 0;
09116       p->subs[idx].f.data.ptr = NULL;
09117       p->subs[idx].f.datalen= 0;
09118    }
09119    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09120       /* Perform busy detection etc on the dahdi line */
09121       int mute;
09122 
09123       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09124 
09125       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09126       mute = ast_dsp_was_muted(p->dsp);
09127       if (p->muting != mute) {
09128          p->muting = mute;
09129          dahdi_confmute(p, mute);
09130       }
09131 
09132       if (f) {
09133          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09134             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09135                /* Treat this as a "hangup" instead of a "busy" on the assumption that
09136                   a busy */
09137                f = NULL;
09138             }
09139          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09140             || f->frametype == AST_FRAME_DTMF_END) {
09141 #ifdef HAVE_PRI
09142             if (dahdi_sig_pri_lib_handles(p->sig)
09143                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09144                && p->pri
09145                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09146                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09147                /* Don't accept in-band DTMF when in overlap dial mode */
09148                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09149                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09150                   f->subclass.integer, f->subclass.integer, ast->name);
09151 
09152                f->frametype = AST_FRAME_NULL;
09153                f->subclass.integer = 0;
09154             }
09155 #endif
09156             /* DSP clears us of being pulse */
09157             p->pulsedial = 0;
09158          } else if (p->waitingfordt.tv_sec) {
09159             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09160                p->waitingfordt.tv_sec = 0;
09161                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09162                f=NULL;
09163             } else if (f->frametype == AST_FRAME_VOICE) {
09164                f->frametype = AST_FRAME_NULL;
09165                f->subclass.integer = 0;
09166                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) {
09167                   p->waitingfordt.tv_sec = 0;
09168                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09169                   ast_dsp_set_features(p->dsp, p->dsp_features);
09170                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09171                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09172                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09173                      if (res < 0) {
09174                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09175                         p->dop.dialstr[0] = '\0';
09176                         ast_mutex_unlock(&p->lock);
09177                         return NULL;
09178                      } else {
09179                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09180                         p->dialing = 1;
09181                         p->dop.dialstr[0] = '\0';
09182                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09183                         ast_setstate(ast, AST_STATE_DIALING);
09184                      }
09185                   }
09186                }
09187             }
09188          }
09189       }
09190    } else
09191       f = &p->subs[idx].f;
09192 
09193    if (f) {
09194       switch (f->frametype) {
09195       case AST_FRAME_DTMF_BEGIN:
09196       case AST_FRAME_DTMF_END:
09197          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09198             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09199          } else {
09200             dahdi_handle_dtmf(ast, idx, &f);
09201          }
09202          break;
09203       case AST_FRAME_VOICE:
09204          if (p->cidspill || p->cid_suppress_expire) {
09205             /* We are/were sending a caller id spill.  Suppress any echo. */
09206             p->subs[idx].f.frametype = AST_FRAME_NULL;
09207             p->subs[idx].f.subclass.integer = 0;
09208             p->subs[idx].f.samples = 0;
09209             p->subs[idx].f.mallocd = 0;
09210             p->subs[idx].f.offset = 0;
09211             p->subs[idx].f.data.ptr = NULL;
09212             p->subs[idx].f.datalen= 0;
09213          }
09214          break;
09215       default:
09216          break;
09217       }
09218    }
09219 
09220    ast_mutex_unlock(&p->lock);
09221    return f;
09222 }

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

Definition at line 13517 of file chan_dahdi.c.

References analog_lib_handles(), analog_request(), ast_atomic_fetchadd_int(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_STATE_RESERVED, AST_TRANS_CAP_DIGITAL, available(), dahdi_starting_point::backwards, dahdi_starting_point::cadance, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_starting_point::channelmatch, dahdi_pvt::confirmanswer, dahdi_new(), dahdi_sig_pri_lib_handles(), determine_starting_point(), dahdi_pvt::dialstring, dahdi_pvt::distinctivering, dahdi_pvt::dnid, duplicate_pseudo(), dahdi_starting_point::groupmatch, ifend, iflist, iflock, is_group_or_channel_match(), ast_channel::linkedid, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2call, dahdi_pvt::next, sig_pri_span::num_call_waiting_calls, dahdi_pvt::oprmode, dahdi_starting_point::opt, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_pvt::radio, restart_monitor(), round_robin, dahdi_starting_point::roundrobin, dahdi_starting_point::rr_starting_point, dahdi_pvt::sig, SIG_PRI_DEFLAW, sig_pri_extract_called_num_subaddr(), SIG_PRI_LIB_HANDLE_CASES, sig_pri_request(), dahdi_pvt::sig_pvt, SIG_SS7, SIG_SS7_DEFLAW, sig_ss7_request(), dahdi_starting_point::span, SUB_CALLWAIT, and SUB_REAL.

13518 {
13519    int callwait = 0;
13520    struct dahdi_pvt *p;
13521    struct ast_channel *tmp = NULL;
13522    struct dahdi_pvt *exitpvt;
13523    int channelmatched = 0;
13524    int groupmatched = 0;
13525 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13526    int transcapdigital = 0;
13527 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13528    struct dahdi_starting_point start;
13529 
13530    ast_mutex_lock(&iflock);
13531    p = determine_starting_point(data, &start);
13532    if (!p) {
13533       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13534       ast_mutex_unlock(&iflock);
13535       return NULL;
13536    }
13537 
13538    /* Search for an unowned channel */
13539    exitpvt = p;
13540    while (p && !tmp) {
13541       if (start.roundrobin)
13542          round_robin[start.rr_starting_point] = p;
13543 
13544       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13545          && available(&p, channelmatched)) {
13546          ast_debug(1, "Using channel %d\n", p->channel);
13547 
13548          callwait = (p->owner != NULL);
13549 #ifdef HAVE_OPENR2
13550          if (p->mfcr2) {
13551             ast_mutex_lock(&p->lock);
13552             if (p->mfcr2call) {
13553                ast_mutex_unlock(&p->lock);
13554                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13555                goto next;
13556             }
13557             p->mfcr2call = 1;
13558             ast_mutex_unlock(&p->lock);
13559          }
13560 #endif
13561          if (p->channel == CHAN_PSEUDO) {
13562             p = duplicate_pseudo(p);
13563             if (!p) {
13564                break;
13565             }
13566          }
13567 
13568          p->distinctivering = 0;
13569          /* Make special notes */
13570          switch (start.opt) {
13571          case '\0':
13572             /* No option present. */
13573             break;
13574          case 'c':
13575             /* Confirm answer */
13576             p->confirmanswer = 1;
13577             break;
13578          case 'r':
13579             /* Distinctive ring */
13580             p->distinctivering = start.cadance;
13581             break;
13582          case 'd':
13583 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13584             /* If this is an ISDN call, make it digital */
13585             transcapdigital = AST_TRANS_CAP_DIGITAL;
13586 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13587             break;
13588          default:
13589             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13590             break;
13591          }
13592 
13593          p->outgoing = 1;
13594          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13595             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13596 #ifdef HAVE_PRI
13597          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13598             /*
13599              * We already have the B channel reserved for this call.  We
13600              * just need to make sure that dahdi_hangup() has completed
13601              * cleaning up before continuing.
13602              */
13603             ast_mutex_lock(&p->lock);
13604             ast_mutex_unlock(&p->lock);
13605 
13606             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13607                sizeof(p->dnid));
13608             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13609 #endif
13610 #if defined(HAVE_SS7)
13611          } else if (p->sig == SIG_SS7) {
13612             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13613 #endif   /* defined(HAVE_SS7) */
13614          } else {
13615             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13616          }
13617          if (!tmp) {
13618             p->outgoing = 0;
13619 #if defined(HAVE_PRI)
13620             switch (p->sig) {
13621             case SIG_PRI_LIB_HANDLE_CASES:
13622 #if defined(HAVE_PRI_CALL_WAITING)
13623                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13624                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13625                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13626                }
13627 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13628                /*
13629                 * This should be the last thing to clear when we are done with
13630                 * the channel.
13631                 */
13632                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13633                break;
13634             default:
13635                break;
13636             }
13637 #endif   /* defined(HAVE_PRI) */
13638          } else {
13639             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13640          }
13641          break;
13642       }
13643 #ifdef HAVE_OPENR2
13644 next:
13645 #endif
13646       if (start.backwards) {
13647          p = p->prev;
13648          if (!p)
13649             p = ifend;
13650       } else {
13651          p = p->next;
13652          if (!p)
13653             p = iflist;
13654       }
13655       /* stop when you roll to the one that we started from */
13656       if (p == exitpvt)
13657          break;
13658    }
13659    ast_mutex_unlock(&iflock);
13660    restart_monitor();
13661    if (cause && !tmp) {
13662       if (callwait || channelmatched) {
13663          *cause = AST_CAUSE_BUSY;
13664       } else if (groupmatched) {
13665          *cause = AST_CAUSE_CONGESTION;
13666       } else {
13667          /*
13668           * We did not match any channel requested.
13669           * Dialplan error requesting non-existant channel?
13670           */
13671       }
13672    }
13673 
13674    return tmp;
13675 }

static int dahdi_restart ( void   )  [static]

Definition at line 14952 of file chan_dahdi.c.

References ast_debug, ast_mutex_lock, AST_PTHREADT_NULL, ast_verb, dahdi_r2_destroy_links(), dahdi_softhangup_all(), sig_pri_span::master, dahdi_pri::pri, dahdi_pvt::pri, pris, and restart_lock.

Referenced by action_dahdirestart(), and dahdi_restart_cmd().

14953 {
14954 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14955    int i, j;
14956 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
14957    int cancel_code;
14958    struct dahdi_pvt *p;
14959 
14960    ast_mutex_lock(&restart_lock);
14961    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14962    dahdi_softhangup_all();
14963    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14964 #ifdef HAVE_OPENR2
14965    dahdi_r2_destroy_links();
14966 #endif
14967 
14968 #if defined(HAVE_PRI)
14969    for (i = 0; i < NUM_SPANS; i++) {
14970       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
14971          cancel_code = pthread_cancel(pris[i].pri.master);
14972          pthread_kill(pris[i].pri.master, SIGURG);
14973          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].pri.master, cancel_code);
14974          pthread_join(pris[i].pri.master, NULL);
14975          ast_debug(4, "Joined thread of span %d\n", i);
14976       }
14977    }
14978 #endif
14979 
14980 #if defined(HAVE_SS7)
14981    for (i = 0; i < NUM_SPANS; i++) {
14982       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
14983          cancel_code = pthread_cancel(linksets[i].ss7.master);
14984          pthread_kill(linksets[i].ss7.master, SIGURG);
14985          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].ss7.master, cancel_code);
14986          pthread_join(linksets[i].ss7.master, NULL);
14987          ast_debug(4, "Joined thread of span %d\n", i);
14988       }
14989    }
14990 #endif   /* defined(HAVE_SS7) */
14991 
14992    ast_mutex_lock(&monlock);
14993    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14994       cancel_code = pthread_cancel(monitor_thread);
14995       pthread_kill(monitor_thread, SIGURG);
14996       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14997       pthread_join(monitor_thread, NULL);
14998       ast_debug(4, "Joined monitor thread\n");
14999    }
15000    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15001 
15002    ast_mutex_lock(&ss_thread_lock);
15003    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15004       int x = DAHDI_FLASH;
15005       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15006 
15007       ast_mutex_lock(&iflock);
15008       for (p = iflist; p; p = p->next) {
15009          if (p->owner) {
15010             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15011             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15012          }
15013       }
15014       ast_mutex_unlock(&iflock);
15015       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15016    }
15017 
15018    /* ensure any created channels before monitor threads were stopped are hungup */
15019    dahdi_softhangup_all();
15020    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15021    destroy_all_channels();
15022    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15023 
15024    ast_mutex_unlock(&monlock);
15025 
15026 #ifdef HAVE_PRI
15027    for (i = 0; i < NUM_SPANS; i++) {
15028       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15029          dahdi_close_pri_fd(&(pris[i]), j);
15030    }
15031 
15032    memset(pris, 0, sizeof(pris));
15033    for (i = 0; i < NUM_SPANS; i++) {
15034       sig_pri_init_pri(&pris[i].pri);
15035    }
15036    pri_set_error(dahdi_pri_error);
15037    pri_set_message(dahdi_pri_message);
15038 #endif
15039 #if defined(HAVE_SS7)
15040    for (i = 0; i < NUM_SPANS; i++) {
15041       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15042          dahdi_close_ss7_fd(&(linksets[i]), j);
15043    }
15044 
15045    memset(linksets, 0, sizeof(linksets));
15046    for (i = 0; i < NUM_SPANS; i++) {
15047       sig_ss7_init_linkset(&linksets[i].ss7);
15048    }
15049    ss7_set_error(dahdi_ss7_error);
15050    ss7_set_message(dahdi_ss7_message);
15051 #endif   /* defined(HAVE_SS7) */
15052 
15053    if (setup_dahdi(2) != 0) {
15054       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15055       ast_mutex_unlock(&ss_thread_lock);
15056       return 1;
15057    }
15058    ast_mutex_unlock(&ss_thread_lock);
15059    ast_mutex_unlock(&restart_lock);
15060    return 0;
15061 }

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

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

15064 {
15065    switch (cmd) {
15066    case CLI_INIT:
15067       e->command = "dahdi restart";
15068       e->usage =
15069          "Usage: dahdi restart\n"
15070          "  Restarts the DAHDI channels: destroys them all and then\n"
15071          "  re-reads them from chan_dahdi.conf.\n"
15072          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15073          "";
15074       return NULL;
15075    case CLI_GENERATE:
15076       return NULL;
15077    }
15078    if (a->argc != 2)
15079       return CLI_SHOWUSAGE;
15080 
15081    if (dahdi_restart() != 0)
15082       return CLI_FAILURE;
15083    return CLI_SUCCESS;
15084 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

Definition at line 7548 of file chan_dahdi.c.

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

Referenced by __dahdi_exception(), dahdi_handle_event(), and my_ring().

07549 {
07550    int x;
07551    int res;
07552    /* Make sure our transmit state is on hook */
07553    x = 0;
07554    x = DAHDI_ONHOOK;
07555    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07556    do {
07557       x = DAHDI_RING;
07558       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07559       if (res) {
07560          switch (errno) {
07561          case EBUSY:
07562          case EINTR:
07563             /* Wait just in case */
07564             usleep(10000);
07565             continue;
07566          case EINPROGRESS:
07567             res = 0;
07568             break;
07569          default:
07570             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07571             res = 0;
07572          }
07573       }
07574    } while (res);
07575    return res;
07576 }

static int dahdi_send_callrerouting_facility_exec ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 5863 of file chan_dahdi.c.

References ast_channel::_state, args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), dahdi_tech, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::name, parse(), pri_send_callrerouting_facility_exec(), dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, ast_channel::tech, and ast_channel::tech_pvt.

Referenced by load_module().

05864 {
05865    /* Data will be our digit string */
05866    struct dahdi_pvt *pvt;
05867    char *parse;
05868    int res = -1;
05869    AST_DECLARE_APP_ARGS(args,
05870       AST_APP_ARG(destination);
05871       AST_APP_ARG(original);
05872       AST_APP_ARG(reason);
05873    );
05874 
05875    if (ast_strlen_zero(data)) {
05876       ast_log(LOG_DEBUG, "No data sent to application!\n");
05877       return -1;
05878    }
05879    if (chan->tech != &dahdi_tech) {
05880       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05881       return -1;
05882    }
05883    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05884    if (!pvt) {
05885       ast_log(LOG_DEBUG, "Unable to find technology private\n");
05886       return -1;
05887    }
05888    switch (pvt->sig) {
05889    case SIG_PRI_LIB_HANDLE_CASES:
05890       break;
05891    default:
05892       ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05893          chan->name);
05894       return -1;
05895    }
05896 
05897    parse = ast_strdupa(data);
05898    AST_STANDARD_APP_ARGS(args, parse);
05899 
05900    if (ast_strlen_zero(args.destination)) {
05901       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05902       return -1;
05903    }
05904 
05905    if (ast_strlen_zero(args.original)) {
05906       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05907       args.original = NULL;
05908    }
05909 
05910    if (ast_strlen_zero(args.reason)) {
05911       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05912       args.reason = NULL;
05913    }
05914 
05915    pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05916       args.original, args.reason);
05917 
05918    return res;
05919 }

static int dahdi_send_keypad_facility_exec ( struct ast_channel chan,
const char *  digits 
) [static]

Definition at line 5836 of file chan_dahdi.c.

References ast_debug, ast_strlen_zero(), pri_send_keypad_facility_exec(), dahdi_pvt::sig_pvt, and ast_channel::tech_pvt.

Referenced by load_module().

05837 {
05838    /* Data will be our digit string */
05839    struct dahdi_pvt *p;
05840 
05841    if (ast_strlen_zero(digits)) {
05842       ast_debug(1, "No digit string sent to application!\n");
05843       return -1;
05844    }
05845 
05846    p = (struct dahdi_pvt *)chan->tech_pvt;
05847 
05848    if (!p) {
05849       ast_debug(1, "Unable to find technology private\n");
05850       return -1;
05851    }
05852 
05853    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05854 
05855    return 0;
05856 }

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

Definition at line 18511 of file chan_dahdi.c.

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

18512 {
18513 #define  END_SILENCE_LEN 400
18514 #define  HEADER_MS 50
18515 #define  TRAILER_MS 5
18516 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18517 #define  ASCII_BYTES_PER_CHAR 80
18518 
18519    unsigned char *buf,*mybuf;
18520    struct dahdi_pvt *p = c->tech_pvt;
18521    struct pollfd fds[1];
18522    int size,res,fd,len,x;
18523    int bytes=0;
18524    /* Initial carrier (imaginary) */
18525    float cr = 1.0;
18526    float ci = 0.0;
18527    float scont = 0.0;
18528    int idx;
18529 
18530    idx = dahdi_get_index(c, p, 0);
18531    if (idx < 0) {
18532       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18533       return -1;
18534    }
18535    if (!text[0]) return(0); /* if nothing to send, don't */
18536    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18537    if (p->mate)
18538       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18539    else
18540       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18541    if (!buf)
18542       return -1;
18543    mybuf = buf;
18544    if (p->mate) {
18545       int codec = AST_LAW(p);
18546       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18547          PUT_CLID_MARKMS;
18548       }
18549       /* Put actual message */
18550       for (x = 0; text[x]; x++) {
18551          PUT_CLID(text[x]);
18552       }
18553       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18554          PUT_CLID_MARKMS;
18555       }
18556       len = bytes;
18557       buf = mybuf;
18558    } else {
18559       len = tdd_generate(p->tdd, buf, text);
18560       if (len < 1) {
18561          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18562          ast_free(mybuf);
18563          return -1;
18564       }
18565    }
18566    memset(buf + len, 0x7f, END_SILENCE_LEN);
18567    len += END_SILENCE_LEN;
18568    fd = p->subs[idx].dfd;
18569    while (len) {
18570       if (ast_check_hangup(c)) {
18571          ast_free(mybuf);
18572          return -1;
18573       }
18574       size = len;
18575       if (size > READ_SIZE)
18576          size = READ_SIZE;
18577       fds[0].fd = fd;
18578       fds[0].events = POLLOUT | POLLPRI;
18579       fds[0].revents = 0;
18580       res = poll(fds, 1, -1);
18581       if (!res) {
18582          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18583          continue;
18584       }
18585       /* if got exception */
18586       if (fds[0].revents & POLLPRI) {
18587          ast_free(mybuf);
18588          return -1;
18589       }
18590       if (!(fds[0].revents & POLLOUT)) {
18591          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18592          continue;
18593       }
18594       res = write(fd, buf, size);
18595       if (res != size) {
18596          if (res == -1) {
18597             ast_free(mybuf);
18598             return -1;
18599          }
18600          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18601          break;
18602       }
18603       len -= size;
18604       buf += size;
18605    }
18606    ast_free(mybuf);
18607    return(0);
18608 }

static char* dahdi_set_dnd ( 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_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, dahdi_pvt::next, and ast_cli_entry::usage.

15679 {
15680    int channel;
15681    int on;
15682    struct dahdi_pvt *dahdi_chan = NULL;
15683 
15684    switch (cmd) {
15685    case CLI_INIT:
15686       e->command = "dahdi set dnd";
15687       e->usage =
15688          "Usage: dahdi set dnd <chan#> <on|off>\n"
15689          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15690          "  Changes take effect immediately.\n"
15691          "  <chan num> is the channel number\n"
15692          "  <on|off> Enable or disable DND mode?\n"
15693          ;
15694       return NULL;
15695    case CLI_GENERATE:
15696       return NULL;
15697    }
15698 
15699    if (a->argc != 5)
15700       return CLI_SHOWUSAGE;
15701 
15702    if ((channel = atoi(a->argv[3])) <= 0) {
15703       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15704       return CLI_SHOWUSAGE;
15705    }
15706 
15707    if (ast_true(a->argv[4]))
15708       on = 1;
15709    else if (ast_false(a->argv[4]))
15710       on = 0;
15711    else {
15712       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15713       return CLI_SHOWUSAGE;
15714    }
15715 
15716    ast_mutex_lock(&iflock);
15717    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15718       if (dahdi_chan->channel != channel)
15719          continue;
15720 
15721       /* Found the channel. Actually set it */
15722       dahdi_dnd(dahdi_chan, on);
15723       break;
15724    }
15725    ast_mutex_unlock(&iflock);
15726 
15727    if (!dahdi_chan) {
15728       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15729       return CLI_FAILURE;
15730    }
15731 
15732    return CLI_SUCCESS;
15733 }

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

Definition at line 5096 of file chan_dahdi.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_wink(), handle_init_event(), mwi_send_process_buffer(), mwi_send_process_event(), my_off_hook(), and my_on_hook().

05097 {
05098    int x, res;
05099 
05100    x = hs;
05101    res = ioctl(fd, DAHDI_HOOK, &x);
05102 
05103    if (res < 0) {
05104       if (errno == EINPROGRESS)
05105          return 0;
05106       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05107       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05108    }
05109 
05110    return res;
05111 }

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

Definition at line 15538 of file chan_dahdi.c.

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

15539 {
15540    int channel;
15541    int gain;
15542    int tx;
15543    struct dahdi_hwgain hwgain;
15544    struct dahdi_pvt *tmp = NULL;
15545 
15546    switch (cmd) {
15547    case CLI_INIT:
15548       e->command = "dahdi set hwgain";
15549       e->usage =
15550          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15551          "  Sets the hardware gain on a a given channel, overriding the\n"
15552          "   value provided at module loadtime, whether the channel is in\n"
15553          "   use or not.  Changes take effect immediately.\n"
15554          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15555          "   <chan num> is the channel number relative to the device\n"
15556          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15557       return NULL;
15558    case CLI_GENERATE:
15559       return NULL;
15560    }
15561 
15562    if (a->argc != 6)
15563       return CLI_SHOWUSAGE;
15564 
15565    if (!strcasecmp("rx", a->argv[3]))
15566       tx = 0; /* rx */
15567    else if (!strcasecmp("tx", a->argv[3]))
15568       tx = 1; /* tx */
15569    else
15570       return CLI_SHOWUSAGE;
15571 
15572    channel = atoi(a->argv[4]);
15573    gain = atof(a->argv[5])*10.0;
15574 
15575    ast_mutex_lock(&iflock);
15576 
15577    for (tmp = iflist; tmp; tmp = tmp->next) {
15578 
15579       if (tmp->channel != channel)
15580          continue;
15581 
15582       if (tmp->subs[SUB_REAL].dfd == -1)
15583          break;
15584 
15585       hwgain.newgain = gain;
15586       hwgain.tx = tx;
15587       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15588          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15589          ast_mutex_unlock(&iflock);
15590          return CLI_FAILURE;
15591       }
15592       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15593          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15594       break;
15595    }
15596 
15597    ast_mutex_unlock(&iflock);
15598 
15599    if (tmp)
15600       return CLI_SUCCESS;
15601 
15602    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15603    return CLI_FAILURE;
15604 
15605 }

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

Definition at line 15607 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, ast_cli_args::fd, iflist, dahdi_pvt::law, dahdi_pvt::next, dahdi_pvt::rxdrc, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::txdrc, and ast_cli_entry::usage.

15608 {
15609    int channel;
15610    float gain;
15611    int tx;
15612    int res;
15613    struct dahdi_pvt *tmp = NULL;
15614 
15615    switch (cmd) {
15616    case CLI_INIT:
15617       e->command = "dahdi set swgain";
15618       e->usage =
15619          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15620          "  Sets the software gain on a a given channel, overriding the\n"
15621          "   value provided at module loadtime, whether the channel is in\n"
15622          "   use or not.  Changes take effect immediately.\n"
15623          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15624          "   <chan num> is the channel number relative to the device\n"
15625          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15626       return NULL;
15627    case CLI_GENERATE:
15628       return NULL;
15629    }
15630 
15631    if (a->argc != 6)
15632       return CLI_SHOWUSAGE;
15633 
15634    if (!strcasecmp("rx", a->argv[3]))
15635       tx = 0; /* rx */
15636    else if (!strcasecmp("tx", a->argv[3]))
15637       tx = 1; /* tx */
15638    else
15639       return CLI_SHOWUSAGE;
15640 
15641    channel = atoi(a->argv[4]);
15642    gain = atof(a->argv[5]);
15643 
15644    ast_mutex_lock(&iflock);
15645    for (tmp = iflist; tmp; tmp = tmp->next) {
15646 
15647       if (tmp->channel != channel)
15648          continue;
15649 
15650       if (tmp->subs[SUB_REAL].dfd == -1)
15651          break;
15652 
15653       if (tx)
15654          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15655       else
15656          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15657 
15658       if (res) {
15659          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15660          ast_mutex_unlock(&iflock);
15661          return CLI_FAILURE;
15662       }
15663 
15664       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15665          tx ? "tx" : "rx", gain, channel);
15666       break;
15667    }
15668    ast_mutex_unlock(&iflock);
15669 
15670    if (tmp)
15671       return CLI_SUCCESS;
15672 
15673    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15674    return CLI_FAILURE;
15675 
15676 }

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

Definition at line 2559 of file chan_dahdi.c.

Referenced by my_new_pri_ast_channel(), my_new_ss7_ast_channel(), and my_pri_open_media().

02560 {
02561    int res;
02562    res = ioctl(dfd, DAHDI_SETLAW, &law);
02563    if (res)
02564       return res;
02565    return 0;
02566 }

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

Definition at line 4325 of file chan_dahdi.c.

Referenced by analog_ss_thread(), dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), my_all_subchannels_hungup(), my_set_linear_mode(), my_start_cid_detect(), my_stop_cid_detect(), and send_callerid().

04326 {
04327    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04328 }

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

Definition at line 6646 of file chan_dahdi.c.

References ast_check_hangup(), ast_debug, ast_dsp_set_digitmode(), ast_dsp_set_features(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_DIGIT_DETECT, AST_OPTION_ECHOCAN, AST_OPTION_FAX_DETECT, AST_OPTION_OPRMODE, AST_OPTION_RELAXDTMF, AST_OPTION_RXGAIN, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, AST_OPTION_TXGAIN, ast_tdd_gen_ecdisa(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index, dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, disable_dtmf_detect(), dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::dtmfrelax, enable_dtmf_detect(), 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::rxdrc, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), dahdi_pvt::sig, dahdi_pvt::sig_pvt, SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::txdrc, dahdi_pvt::txgain, and ast_channel_tech::type.

06647 {
06648    char *cp;
06649    signed char *scp;
06650    int x;
06651    int idx;
06652    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06653    struct oprmode *oprmode;
06654 
06655 
06656    /* all supported options require data */
06657    if (!p || !data || (datalen < 1)) {
06658       errno = EINVAL;
06659       return -1;
06660    }
06661 
06662    switch (option) {
06663    case AST_OPTION_TXGAIN:
06664       scp = (signed char *) data;
06665       idx = dahdi_get_index(chan, p, 0);
06666       if (idx < 0) {
06667          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06668          return -1;
06669       }
06670       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06671       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06672    case AST_OPTION_RXGAIN:
06673       scp = (signed char *) data;
06674       idx = dahdi_get_index(chan, p, 0);
06675       if (idx < 0) {
06676          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06677          return -1;
06678       }
06679       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06680       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06681    case AST_OPTION_TONE_VERIFY:
06682       if (!p->dsp)
06683          break;
06684       cp = (char *) data;
06685       switch (*cp) {
06686       case 1:
06687          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06688          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06689          break;
06690       case 2:
06691          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06692          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06693          break;
06694       default:
06695          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06696          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06697          break;
06698       }
06699       break;
06700    case AST_OPTION_TDD:
06701       /* turn on or off TDD */
06702       cp = (char *) data;
06703       p->mate = 0;
06704       if (!*cp) { /* turn it off */
06705          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06706          if (p->tdd)
06707             tdd_free(p->tdd);
06708          p->tdd = 0;
06709          break;
06710       }
06711       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06712          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06713       dahdi_disable_ec(p);
06714       /* otherwise, turn it on */
06715       if (!p->didtdd) { /* if havent done it yet */
06716          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06717          unsigned char *buf;
06718          int size, res, fd, len;
06719          struct pollfd fds[1];
06720 
06721          buf = mybuf;
06722          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06723          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06724          len = 40000;
06725          idx = dahdi_get_index(chan, p, 0);
06726          if (idx < 0) {
06727             ast_log(LOG_WARNING, "No index in TDD?\n");
06728             return -1;
06729          }
06730          fd = p->subs[idx].dfd;
06731          while (len) {
06732             if (ast_check_hangup(chan))
06733                return -1;
06734             size = len;
06735             if (size > READ_SIZE)
06736                size = READ_SIZE;
06737             fds[0].fd = fd;
06738             fds[0].events = POLLPRI | POLLOUT;
06739             fds[0].revents = 0;
06740             res = poll(fds, 1, -1);
06741             if (!res) {
06742                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06743                continue;
06744             }
06745             /* if got exception */
06746             if (fds[0].revents & POLLPRI)
06747                return -1;
06748             if (!(fds[0].revents & POLLOUT)) {
06749                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06750                continue;
06751             }
06752             res = write(fd, buf, size);
06753             if (res != size) {
06754                if (res == -1) return -1;
06755                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06756                break;
06757             }
06758             len -= size;
06759             buf += size;
06760          }
06761          p->didtdd = 1; /* set to have done it now */
06762       }
06763       if (*cp == 2) { /* Mate mode */
06764          if (p->tdd)
06765             tdd_free(p->tdd);
06766          p->tdd = 0;
06767          p->mate = 1;
06768          break;
06769       }
06770       if (!p->tdd) { /* if we don't have one yet */
06771          p->tdd = tdd_new(); /* allocate one */
06772       }
06773       break;
06774    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06775       if (!p->dsp)
06776          break;
06777       cp = (char *) data;
06778       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06779          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06780       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06781       break;
06782    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06783 #if defined(HAVE_PRI)
06784       if (dahdi_sig_pri_lib_handles(p->sig)
06785          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06786          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06787          break;
06788       }
06789 #endif   /* defined(HAVE_PRI) */
06790 
06791       cp = (char *) data;
06792       if (!*cp) {
06793          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06794          x = 0;
06795          dahdi_disable_ec(p);
06796       } else {
06797          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06798          x = 1;
06799       }
06800       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06801          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06802       break;
06803    case AST_OPTION_OPRMODE:  /* Operator services mode */
06804       oprmode = (struct oprmode *) data;
06805       /* We don't support operator mode across technologies */
06806       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06807          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06808                chan->tech->type, oprmode->peer->tech->type);
06809          errno = EINVAL;
06810          return -1;
06811       }
06812       pp = oprmode->peer->tech_pvt;
06813       p->oprmode = pp->oprmode = 0;
06814       /* setup peers */
06815       p->oprpeer = pp;
06816       pp->oprpeer = p;
06817       /* setup modes, if any */
06818       if (oprmode->mode)
06819       {
06820          pp->oprmode = oprmode->mode;
06821          p->oprmode = -oprmode->mode;
06822       }
06823       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06824          oprmode->mode, chan->name,oprmode->peer->name);
06825       break;
06826    case AST_OPTION_ECHOCAN:
06827       cp = (char *) data;
06828       if (*cp) {
06829          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06830          dahdi_enable_ec(p);
06831       } else {
06832          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06833          dahdi_disable_ec(p);
06834       }
06835       break;
06836    case AST_OPTION_DIGIT_DETECT:
06837       cp = (char *) data;
06838       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06839       if (*cp) {
06840          enable_dtmf_detect(p);
06841       } else {
06842          disable_dtmf_detect(p);
06843       }
06844       break;
06845    case AST_OPTION_FAX_DETECT:
06846       cp = (char *) data;
06847       if (p->dsp) {
06848          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06849          if (*cp) {
06850             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06851          } else {
06852             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06853          }
06854          ast_dsp_set_features(p->dsp, p->dsp_features);
06855       }
06856       break;
06857    default:
06858       return -1;
06859    }
06860    errno = 0;
06861 
06862    return 0;
06863 }

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

Definition at line 15182 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::callwaitcas, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_ton, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, dahdi_pvt::confno, dahdi_pvt::context, dahdi_dnd(), dahdi_pvt::destroy, dahdi_pvt::dialing, dahdi_pvt::dsp, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echocanon, dahdi_pvt::exten, dahdi_pvt::faxhandled, ast_cli_args::fd, HAVE_PRI_SUBADDR, dahdi_pvt::head, iflist, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pvt::law_default, dahdi_subchannel::linear, dahdi_pvt::mailbox, dahdi_pvt::master, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_allow_collect_calls, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::mfcr2_forced_release, ast_channel::name, ast_variable::name, ast_variable::next, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::params, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, S_OR, dahdi_pvt::sig, sig2str, dahdi_pvt::slaves, dahdi_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, dahdi_pvt::tdd, dahdi_pvt::txdrc, dahdi_pvt::txgain, ast_cli_entry::usage, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

15183 {
15184    int channel;
15185    struct dahdi_pvt *tmp = NULL;
15186    struct dahdi_confinfo ci;
15187    struct dahdi_params ps;
15188    int x;
15189 
15190    switch (cmd) {
15191    case CLI_INIT:
15192       e->command = "dahdi show channel";
15193       e->usage =
15194          "Usage: dahdi show channel <chan num>\n"
15195          "  Detailed information about a given channel\n";
15196       return NULL;
15197    case CLI_GENERATE:
15198       return NULL;
15199    }
15200 
15201    if (a->argc != 4)
15202       return CLI_SHOWUSAGE;
15203 
15204    channel = atoi(a->argv[3]);
15205 
15206    ast_mutex_lock(&iflock);
15207    for (tmp = iflist; tmp; tmp = tmp->next) {
15208       if (tmp->channel == channel) {
15209          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15210          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15211          ast_cli(a->fd, "Span: %d\n", tmp->span);
15212          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15213          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15214          ast_cli(a->fd, "Context: %s\n", tmp->context);
15215          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15216          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15217 #if defined(HAVE_PRI)
15218 #if defined(HAVE_PRI_SUBADDR)
15219          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15220 #endif   /* defined(HAVE_PRI_SUBADDR) */
15221 #endif   /* defined(HAVE_PRI) */
15222          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15223          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15224          if (tmp->vars) {
15225             struct ast_variable *v;
15226             ast_cli(a->fd, "Variables:\n");
15227             for (v = tmp->vars ; v ; v = v->next)
15228                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15229          }
15230          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15231          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15232          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15233          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15234          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15235          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)" : "");
15236          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)" : "");
15237          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)" : "");
15238          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15239          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15240          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15241          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15242          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15243          if (tmp->busydetect) {
15244 #if defined(BUSYDETECT_TONEONLY)
15245             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15246 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15247             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15248 #endif
15249 #ifdef BUSYDETECT_DEBUG
15250             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15251 #endif
15252             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15253             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
15254          }
15255          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15256          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15257          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15258          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15259          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15260          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15261          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15262          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15263          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15264          ast_cli(a->fd, "Echo Cancellation:\n");
15265 
15266          if (tmp->echocancel.head.tap_length) {
15267             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15268             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15269                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15270             }
15271             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15272          } else {
15273             ast_cli(a->fd, "\tnone\n");
15274          }
15275          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15276          if (tmp->master)
15277             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15278          for (x = 0; x < MAX_SLAVES; x++) {
15279             if (tmp->slaves[x])
15280                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15281          }
15282 #ifdef HAVE_OPENR2
15283          if (tmp->mfcr2) {
15284             char calldir[OR2_MAX_PATH];
15285             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15286             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15287             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15288             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15289             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15290             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15291             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15292             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15293             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15294             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15295             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15296 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15297             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15298 #endif
15299             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15300             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15301             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15302             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15303             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15304             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15305             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15306             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15307             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15308             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15309             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15310             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15311          }
15312 #endif
15313 #if defined(HAVE_SS7)
15314          if (tmp->ss7) {
15315             struct sig_ss7_chan *chan = tmp->sig_pvt;
15316 
15317             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15318          }
15319 #endif   /* defined(HAVE_SS7) */
15320 #ifdef HAVE_PRI
15321          if (tmp->pri) {
15322             struct sig_pri_chan *chan = tmp->sig_pvt;
15323 
15324             ast_cli(a->fd, "PRI Flags: ");
15325             if (chan->resetting)
15326                ast_cli(a->fd, "Resetting ");
15327             if (chan->call)
15328                ast_cli(a->fd, "Call ");
15329             if (chan->allocated) {
15330                ast_cli(a->fd, "Allocated ");
15331             }
15332             ast_cli(a->fd, "\n");
15333             if (tmp->logicalspan)
15334                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15335             else
15336                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15337          }
15338 #endif
15339          memset(&ci, 0, sizeof(ci));
15340          ps.channo = tmp->channel;
15341          if (tmp->subs[SUB_REAL].dfd > -1) {
15342             memset(&ci, 0, sizeof(ci));
15343             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15344                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15345             }
15346             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15347                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15348             }
15349             memset(&ps, 0, sizeof(ps));
15350             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15351                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15352             } else {
15353                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15354             }
15355          }
15356          if (ISTRUNK(tmp)) {
15357             ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
15358             if (!ast_strlen_zero(progzone))
15359                ast_cli(a->fd, "Progress Zone: %s\n", progzone);
15360             ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
15361             if(tmp->busydetect) {
15362                ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
15363                if(tmp->busytonelength > 0) {
15364                   ast_cli(a->fd, "Busy Pattern:\n");
15365                   ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
15366                   if (tmp->busyquietlength > 0) 
15367                      ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
15368                   else 
15369                      ast_cli(a->fd, " -- Detect Tone Only\n");
15370                   if(tmp->busyfuzziness > 0)
15371                      ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
15372                }
15373             }
15374          }
15375          ast_mutex_unlock(&iflock);
15376          return CLI_SUCCESS;
15377       }
15378    }
15379    ast_mutex_unlock(&iflock);
15380 
15381    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15382    return CLI_FAILURE;
15383 }

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

Definition at line 15096 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, dahdi_pvt::context, ast_cli_args::fd, FORMAT2, dahdi_pvt::group, iflist, dahdi_pvt::next, and ast_cli_entry::usage.

15097 {
15098 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15099 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15100    unsigned int targetnum = 0;
15101    int filtertype = 0;
15102    struct dahdi_pvt *tmp = NULL;
15103    char tmps[20] = "";
15104    char statestr[20] = "";
15105    char blockstr[20] = "";
15106 
15107    switch (cmd) {
15108    case CLI_INIT:
15109       e->command = "dahdi show channels [group|context]";
15110       e->usage =
15111          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15112          "  Shows a list of available channels with optional filtering\n"
15113          "  <group> must be a number between 0 and 63\n";
15114       return NULL;
15115    case CLI_GENERATE:
15116       return NULL;
15117    }
15118 
15119    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15120 
15121    if (!((a->argc == 3) || (a->argc == 5)))
15122       return CLI_SHOWUSAGE;
15123 
15124    if (a->argc == 5) {
15125       if (!strcasecmp(a->argv[3], "group")) {
15126          targetnum = atoi(a->argv[4]);
15127          if ((targetnum < 0) || (targetnum > 63))
15128             return CLI_SHOWUSAGE;
15129          targetnum = 1 << targetnum;
15130          filtertype = 1;
15131       } else if (!strcasecmp(a->argv[3], "context")) {
15132          filtertype = 2;
15133       }
15134    }
15135 
15136    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15137    ast_mutex_lock(&iflock);
15138    for (tmp = iflist; tmp; tmp = tmp->next) {
15139       if (filtertype) {
15140          switch(filtertype) {
15141          case 1: /* dahdi show channels group <group> */
15142             if (!(tmp->group & targetnum)) {
15143                continue;
15144             }
15145             break;
15146          case 2: /* dahdi show channels context <context> */
15147             if (strcasecmp(tmp->context, a->argv[4])) {
15148                continue;
15149             }
15150             break;
15151          default:
15152             break;
15153          }
15154       }
15155       if (tmp->channel > 0) {
15156          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15157       } else
15158          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15159 
15160       if (tmp->locallyblocked)
15161          blockstr[0] = 'L';
15162       else
15163          blockstr[0] = ' ';
15164 
15165       if (tmp->remotelyblocked)
15166          blockstr[1] = 'R';
15167       else
15168          blockstr[1] = ' ';
15169 
15170       blockstr[2] = '\0';
15171 
15172       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15173 
15174       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15175    }
15176    ast_mutex_unlock(&iflock);
15177    return CLI_SUCCESS;
15178 #undef FORMAT
15179 #undef FORMAT2
15180 }

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

Definition at line 15422 of file chan_dahdi.c.

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

15423 {
15424    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15425    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15426    int span;
15427    int res;
15428    char alarmstr[50];
15429 
15430    int ctl;
15431    struct dahdi_spaninfo s;
15432 
15433    switch (cmd) {
15434    case CLI_INIT:
15435       e->command = "dahdi show status";
15436       e->usage =
15437          "Usage: dahdi show status\n"
15438          "       Shows a list of DAHDI cards with status\n";
15439       return NULL;
15440    case CLI_GENERATE:
15441       return NULL;
15442    }
15443    ctl = open("/dev/dahdi/ctl", O_RDWR);
15444    if (ctl < 0) {
15445       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15446       return CLI_FAILURE;
15447    }
15448    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15449 
15450    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15451       s.spanno = span;
15452       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15453       if (res) {
15454          continue;
15455       }
15456       alarmstr[0] = '\0';
15457       if (s.alarms > 0) {
15458          if (s.alarms & DAHDI_ALARM_BLUE)
15459             strcat(alarmstr, "BLU/");
15460          if (s.alarms & DAHDI_ALARM_YELLOW)
15461             strcat(alarmstr, "YEL/");
15462          if (s.alarms & DAHDI_ALARM_RED)
15463             strcat(alarmstr, "RED/");
15464          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15465             strcat(alarmstr, "LB/");
15466          if (s.alarms & DAHDI_ALARM_RECOVER)
15467             strcat(alarmstr, "REC/");
15468          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15469             strcat(alarmstr, "NOP/");
15470          if (!strlen(alarmstr))
15471             strcat(alarmstr, "UUU/");
15472          if (strlen(alarmstr)) {
15473             /* Strip trailing / */
15474             alarmstr[strlen(alarmstr) - 1] = '\0';
15475          }
15476       } else {
15477          if (s.numchans)
15478             strcpy(alarmstr, "OK");
15479          else
15480             strcpy(alarmstr, "UNCONFIGURED");
15481       }
15482 
15483       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15484          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15485          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15486          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15487          "CAS",
15488          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15489          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15490          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15491          "Unk",
15492          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15493             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15494             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15495          lbostr[s.lbo]
15496          );
15497    }
15498    close(ctl);
15499 
15500    return CLI_SUCCESS;
15501 #undef FORMAT
15502 #undef FORMAT2
15503 }

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

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

15506 {
15507    int pseudo_fd = -1;
15508    struct dahdi_versioninfo vi;
15509 
15510    switch (cmd) {
15511    case CLI_INIT:
15512       e->command = "dahdi show version";
15513       e->usage =
15514          "Usage: dahdi show version\n"
15515          "       Shows the DAHDI version in use\n";
15516       return NULL;
15517    case CLI_GENERATE:
15518       return NULL;
15519    }
15520    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15521       ast_cli(a->fd, "Failed to open control file to get version.\n");
15522       return CLI_SUCCESS;
15523    }
15524 
15525    strcpy(vi.version, "Unknown");
15526    strcpy(vi.echo_canceller, "Unknown");
15527 
15528    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15529       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15530    else
15531       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15532 
15533    close(pseudo_fd);
15534 
15535    return CLI_SUCCESS;
15536 }

static char* dahdi_sig2str ( int  sig  )  [static]

Definition at line 4546 of file chan_dahdi.c.

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

04547 {
04548    static char buf[256];
04549    switch (sig) {
04550    case SIG_EM:
04551       return "E & M Immediate";
04552    case SIG_EMWINK:
04553       return "E & M Wink";
04554    case SIG_EM_E1:
04555       return "E & M E1";
04556    case SIG_FEATD:
04557       return "Feature Group D (DTMF)";
04558    case SIG_FEATDMF:
04559       return "Feature Group D (MF)";
04560    case SIG_FEATDMF_TA:
04561       return "Feature Groud D (MF) Tandem Access";
04562    case SIG_FEATB:
04563       return "Feature Group B (MF)";
04564    case SIG_E911:
04565       return "E911 (MF)";
04566    case SIG_FGC_CAMA:
04567       return "FGC/CAMA (Dialpulse)";
04568    case SIG_FGC_CAMAMF:
04569       return "FGC/CAMA (MF)";
04570    case SIG_FXSLS:
04571       return "FXS Loopstart";
04572    case SIG_FXSGS:
04573       return "FXS Groundstart";
04574    case SIG_FXSKS:
04575       return "FXS Kewlstart";
04576    case SIG_FXOLS:
04577       return "FXO Loopstart";
04578    case SIG_FXOGS:
04579       return "FXO Groundstart";
04580    case SIG_FXOKS:
04581       return "FXO Kewlstart";
04582    case SIG_PRI:
04583       return "ISDN PRI";
04584    case SIG_BRI:
04585       return "ISDN BRI Point to Point";
04586    case SIG_BRI_PTMP:
04587       return "ISDN BRI Point to MultiPoint";
04588    case SIG_SS7:
04589       return "SS7";
04590    case SIG_MFCR2:
04591       return "MFC/R2";
04592    case SIG_SF:
04593       return "SF (Tone) Immediate";
04594    case SIG_SFWINK:
04595       return "SF (Tone) Wink";
04596    case SIG_SF_FEATD:
04597       return "SF (Tone) with Feature Group D (DTMF)";
04598    case SIG_SF_FEATDMF:
04599       return "SF (Tone) with Feature Group D (MF)";
04600    case SIG_SF_FEATB:
04601       return "SF (Tone) with Feature Group B (MF)";
04602    case 0:
04603       return "Pseudo";
04604    default:
04605       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04606       return buf;
04607    }
04608 }

static int dahdi_sig_pri_lib_handles ( int  signaling  )  [inline, static]

Definition at line 1553 of file chan_dahdi.c.

References SIG_PRI_LIB_HANDLE_CASES.

Referenced by dahdi_bridge(), dahdi_call(), dahdi_cc_callback(), dahdi_digit_end(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_pri_cc_agent_init(), dahdi_queryoption(), dahdi_read(), dahdi_request(), and dahdi_setoption().

01554 {
01555    int handles;
01556 
01557    switch (signaling) {
01558    case SIG_PRI_LIB_HANDLE_CASES:
01559       handles = 1;
01560       break;
01561    default:
01562       handles = 0;
01563       break;
01564    }
01565 
01566    return handles;
01567 }

static void dahdi_softhangup_all ( void   )  [static]

Definition at line 14923 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, dahdi_pvt::lock, ast_channel::name, dahdi_pvt::next, num_restart_pending, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.

Referenced by dahdi_restart().

14924 {
14925    struct dahdi_pvt *p;
14926 retry:
14927    ast_mutex_lock(&iflock);
14928    for (p = iflist; p; p = p->next) {
14929       ast_mutex_lock(&p->lock);
14930       if (p->owner && !p->restartpending) {
14931          if (ast_channel_trylock(p->owner)) {
14932             if (option_debug > 2)
14933                ast_verbose("Avoiding deadlock\n");
14934             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
14935             ast_mutex_unlock(&p->lock);
14936             ast_mutex_unlock(&iflock);
14937             goto retry;
14938          }
14939          if (option_debug > 2)
14940             ast_verbose("Softhanging up on %s\n", p->owner->name);
14941          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14942          p->restartpending = 1;
14943          num_restart_pending++;
14944          ast_channel_unlock(p->owner);
14945       }
14946       ast_mutex_unlock(&p->lock);
14947    }
14948    ast_mutex_unlock(&iflock);
14949 }

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

Definition at line 13857 of file chan_dahdi.c.

References ast_log(), linksets, and dahdi_ss7::ss7.

Referenced by load_module().

13858 {
13859    int i;
13860 
13861    if (ss7) {
13862       for (i = 0; i < NUM_SPANS; i++) {
13863          if (linksets[i].ss7.ss7 == ss7) {
13864             ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13865             return;
13866          }
13867       }
13868    }
13869    ast_log(LOG_ERROR, "%s", s);
13870 }

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

Definition at line 13840 of file chan_dahdi.c.

References ast_verbose, linksets, and dahdi_ss7::ss7.

Referenced by load_module().

13841 {
13842    int i;
13843 
13844    if (ss7) {
13845       for (i = 0; i < NUM_SPANS; i++) {
13846          if (linksets[i].ss7.ss7 == ss7) {
13847             ast_verbose("[%d] %s", i + 1, s);
13848             return;
13849          }
13850       }
13851    }
13852    ast_verbose("%s", s);
13853 }

static int dahdi_status_data_provider_get ( const struct ast_data_search search,
struct ast_data data_root 
) [static]

Definition at line 18280 of file chan_dahdi.c.

References ast_data_add_bool(), ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), ast_data_remove_node(), ast_data_search_match(), ast_log(), errno, and lbostr.

18282 {
18283    int ctl, res, span;
18284    struct ast_data *data_span, *data_alarms;
18285    struct dahdi_spaninfo s;
18286 
18287    ctl = open("/dev/dahdi/ctl", O_RDWR);
18288    if (ctl < 0) {
18289       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18290       return -1;
18291    }
18292    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18293       s.spanno = span;
18294       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18295       if (res) {
18296          continue;
18297       }
18298 
18299       data_span = ast_data_add_node(data_root, "span");
18300       if (!data_span) {
18301          continue;
18302       }
18303       ast_data_add_str(data_span, "description", s.desc);
18304 
18305       /* insert the alarms status */
18306       data_alarms = ast_data_add_node(data_span, "alarms");
18307       if (!data_alarms) {
18308          continue;
18309       }
18310 
18311       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18312       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18313       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18314       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18315       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18316       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18317 
18318       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18319       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18320       ast_data_add_int(data_span, "crc4", s.crc4count);
18321       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18322                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18323                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18324                      "CAS");
18325       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18326                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18327                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18328                      "Unknown");
18329       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18330                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18331                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18332       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18333 
18334       /* if this span doesn't match remove it. */
18335       if (!ast_data_search_match(search, data_span)) {
18336          ast_data_remove_node(data_root, data_span);
18337       }
18338    }
18339    close(ctl);
18340 
18341    return 0;
18342 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

Definition at line 4888 of file chan_dahdi.c.

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

Referenced by dahdi_handle_event(), and my_train_echocanceller().

04889 {
04890    int x;
04891    int res;
04892 
04893    if (p && p->echocanon && p->echotraining) {
04894       x = p->echotraining;
04895       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04896       if (res)
04897          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04898       else
04899          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04900    } else {
04901       ast_debug(1, "No echo training requested\n");
04902    }
04903 }

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

Definition at line 7078 of file chan_dahdi.c.

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

Referenced by dahdi_bridge(), and dahdi_fixup().

07079 {
07080    /* Unlink a specific slave or all slaves/masters from a given master */
07081    int x;
07082    int hasslaves;
07083    if (!master)
07084       return;
07085    if (needlock) {
07086       ast_mutex_lock(&master->lock);
07087       if (slave) {
07088          while (ast_mutex_trylock(&slave->lock)) {
07089             DEADLOCK_AVOIDANCE(&master->lock);
07090          }
07091       }
07092    }
07093    hasslaves = 0;
07094    for (x = 0; x < MAX_SLAVES; x++) {
07095       if (master->slaves[x]) {
07096          if (!slave || (master->slaves[x] == slave)) {
07097             /* Take slave out of the conference */
07098             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07099             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07100             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07101             master->slaves[x]->master = NULL;
07102             master->slaves[x] = NULL;
07103          } else
07104             hasslaves = 1;
07105       }
07106       if (!hasslaves)
07107          master->inconference = 0;
07108    }
07109    if (!slave) {
07110       if (master->master) {
07111          /* Take master out of the conference */
07112          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07113          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07114          hasslaves = 0;
07115          for (x = 0; x < MAX_SLAVES; x++) {
07116             if (master->master->slaves[x] == master)
07117                master->master->slaves[x] = NULL;
07118             else if (master->master->slaves[x])
07119                hasslaves = 1;
07120          }
07121          if (!hasslaves)
07122             master->master->inconference = 0;
07123       }
07124       master->master = NULL;
07125    }
07126    update_conf(master);
07127    if (needlock) {
07128       if (slave)
07129          ast_mutex_unlock(&slave->lock);
07130       ast_mutex_unlock(&master->lock);
07131    }
07132 }

static void dahdi_unlink_pri_pvt ( struct dahdi_pvt pvt  )  [static]

Definition at line 5618 of file chan_dahdi.c.

References ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::pri, sig_pri_span::pri, and dahdi_pvt::sig_pvt.

Referenced by destroy_dahdi_pvt().

05619 {
05620    unsigned idx;
05621    struct sig_pri_span *pri;
05622 
05623    pri = pvt->pri;
05624    if (!pri) {
05625       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05626       return;
05627    }
05628    ast_mutex_lock(&pri->lock);
05629    for (idx = 0; idx < pri->numchans; ++idx) {
05630       if (pri->pvts[idx] == pvt->sig_pvt) {
05631          pri->pvts[idx] = NULL;
05632          ast_mutex_unlock(&pri->lock);
05633          return;
05634       }
05635    }
05636    ast_mutex_unlock(&pri->lock);
05637 }

static void dahdi_unlink_ss7_pvt ( struct dahdi_pvt pvt  )  [static]

Definition at line 5650 of file chan_dahdi.c.

References ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::sig_pvt, dahdi_pvt::ss7, and sig_ss7_linkset::ss7.

Referenced by destroy_dahdi_pvt().

05651 {
05652    unsigned idx;
05653    struct sig_ss7_linkset *ss7;
05654 
05655    ss7 = pvt->ss7;
05656    if (!ss7) {
05657       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05658       return;
05659    }
05660    ast_mutex_lock(&ss7->lock);
05661    for (idx = 0; idx < ss7->numchans; ++idx) {
05662       if (ss7->pvts[idx] == pvt->sig_pvt) {
05663          ss7->pvts[idx] = NULL;
05664          ast_mutex_unlock(&ss7->lock);
05665          return;
05666       }
05667    }
05668    ast_mutex_unlock(&ss7->lock);
05669 }

static int dahdi_version_data_provider_get ( const struct ast_data_search search,
struct ast_data data_root 
) [static]

Definition at line 18383 of file chan_dahdi.c.

References ast_data_add_str(), ast_log(), and errno.

18385 {
18386    int pseudo_fd = -1;
18387    struct dahdi_versioninfo vi = {
18388       .version = "Unknown",
18389       .echo_canceller = "Unknown"
18390    };
18391 
18392    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18393       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18394       return -1;
18395    }
18396 
18397    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18398       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18399    }
18400 
18401    close(pseudo_fd);
18402 
18403    ast_data_add_str(data_root, "value", vi.version);
18404    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18405 
18406    return 0;
18407 }

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 498 of file chan_dahdi.c.

00499 {
00500    int i, j = 0;
00501    i = DAHDI_IOMUX_SIGEVENT;
00502    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00503       return -1;
00504    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00505       return -1;
00506    return j;
00507 }

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

Definition at line 9724 of file chan_dahdi.c.

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

Referenced by analog_ss_thread(), and my_wink().

09725 {
09726    int j;
09727    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09728    for (;;)
09729    {
09730       /* set bits of interest */
09731       j = DAHDI_IOMUX_SIGEVENT;
09732       /* wait for some happening */
09733       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09734       /* exit loop if we have it */
09735       if (j & DAHDI_IOMUX_SIGEVENT) break;
09736    }
09737    /* get the event info */
09738    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09739    return 0;
09740 }

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

Definition at line 9246 of file chan_dahdi.c.

References ast_debug, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_getformatname(), ast_log(), dahdi_pvt::channel, dahdi_pvt::cidspill, ast_frame_subclass::codec, dahdi_get_index, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialing, errno, ast_frame::frametype, dahdi_subchannel::linear, my_dahdi_write(), ast_channel::name, dahdi_pvt::owner, ast_frame::ptr, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.

09247 {
09248    struct dahdi_pvt *p = ast->tech_pvt;
09249    int res;
09250    int idx;
09251    idx = dahdi_get_index(ast, p, 0);
09252    if (idx < 0) {
09253       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09254       return -1;
09255    }
09256 
09257    /* Write a frame of (presumably voice) data */
09258    if (frame->frametype != AST_FRAME_VOICE) {
09259       if (frame->frametype != AST_FRAME_IMAGE)
09260          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09261       return 0;
09262    }
09263    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09264       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09265       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09266       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09267       return -1;
09268    }
09269    if (p->dialing) {
09270       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09271       return 0;
09272    }
09273    if (!p->owner) {
09274       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09275       return 0;
09276    }
09277    if (p->cidspill) {
09278       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09279          ast->name);
09280       return 0;
09281    }
09282    /* Return if it's not valid data */
09283    if (!frame->data.ptr || !frame->datalen)
09284       return 0;
09285 
09286    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09287       if (!p->subs[idx].linear) {
09288          p->subs[idx].linear = 1;
09289          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09290          if (res)
09291             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09292       }
09293       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09294    } else {
09295       /* x-law already */
09296       if (p->subs[idx].linear) {
09297          p->subs[idx].linear = 0;
09298          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09299          if (res)
09300             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09301       }
09302       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09303    }
09304    if (res < 0) {
09305       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09306       return -1;
09307    }
09308    return 0;
09309 }

static enum analog_event dahdievent_to_analogevent ( int  event  )  [static]

Definition at line 2704 of file chan_dahdi.c.

References ANALOG_EVENT_ALARM, ANALOG_EVENT_DIALCOMPLETE, ANALOG_EVENT_DTMFDOWN, ANALOG_EVENT_DTMFUP, ANALOG_EVENT_EC_DISABLED, ANALOG_EVENT_EC_NLP_DISABLED, ANALOG_EVENT_EC_NLP_ENABLED, ANALOG_EVENT_ERROR, ANALOG_EVENT_HOOKCOMPLETE, ANALOG_EVENT_NEONMWI_ACTIVE, ANALOG_EVENT_NEONMWI_INACTIVE, ANALOG_EVENT_NOALARM, ANALOG_EVENT_ONHOOK, ANALOG_EVENT_POLARITY, ANALOG_EVENT_PULSE_START, ANALOG_EVENT_PULSEDIGIT, ANALOG_EVENT_REMOVED, ANALOG_EVENT_RINGBEGIN, ANALOG_EVENT_RINGEROFF, ANALOG_EVENT_RINGERON, ANALOG_EVENT_RINGOFFHOOK, ANALOG_EVENT_RX_CED_DETECTED, ANALOG_EVENT_TX_CED_DETECTED, and ANALOG_EVENT_WINKFLASH.

Referenced by my_get_callerid(), and my_get_event().

02705 {
02706    enum analog_event res;
02707 
02708    switch (event) {
02709    case DAHDI_EVENT_ONHOOK:
02710       res = ANALOG_EVENT_ONHOOK;
02711       break;
02712    case DAHDI_EVENT_RINGOFFHOOK:
02713       res = ANALOG_EVENT_RINGOFFHOOK;
02714       break;
02715    case DAHDI_EVENT_WINKFLASH:
02716       res = ANALOG_EVENT_WINKFLASH;
02717       break;
02718    case DAHDI_EVENT_ALARM:
02719       res = ANALOG_EVENT_ALARM;
02720       break;
02721    case DAHDI_EVENT_NOALARM:
02722       res = ANALOG_EVENT_NOALARM;
02723       break;
02724    case DAHDI_EVENT_DIALCOMPLETE:
02725       res = ANALOG_EVENT_DIALCOMPLETE;
02726       break;
02727    case DAHDI_EVENT_RINGERON:
02728       res = ANALOG_EVENT_RINGERON;
02729       break;
02730    case DAHDI_EVENT_RINGEROFF:
02731       res = ANALOG_EVENT_RINGEROFF;
02732       break;
02733    case DAHDI_EVENT_HOOKCOMPLETE:
02734       res = ANALOG_EVENT_HOOKCOMPLETE;
02735       break;
02736    case DAHDI_EVENT_PULSE_START:
02737       res = ANALOG_EVENT_PULSE_START;
02738       break;
02739    case DAHDI_EVENT_POLARITY:
02740       res = ANALOG_EVENT_POLARITY;
02741       break;
02742    case DAHDI_EVENT_RINGBEGIN:
02743       res = ANALOG_EVENT_RINGBEGIN;
02744       break;
02745    case DAHDI_EVENT_EC_DISABLED:
02746       res = ANALOG_EVENT_EC_DISABLED;
02747       break;
02748    case DAHDI_EVENT_REMOVED:
02749       res = ANALOG_EVENT_REMOVED;
02750       break;
02751    case DAHDI_EVENT_NEONMWI_ACTIVE:
02752       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02753       break;
02754    case DAHDI_EVENT_NEONMWI_INACTIVE:
02755       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02756       break;
02757 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02758    case DAHDI_EVENT_TX_CED_DETECTED:
02759       res = ANALOG_EVENT_TX_CED_DETECTED;
02760       break;
02761    case DAHDI_EVENT_RX_CED_DETECTED:
02762       res = ANALOG_EVENT_RX_CED_DETECTED;
02763       break;
02764    case DAHDI_EVENT_EC_NLP_DISABLED:
02765       res = ANALOG_EVENT_EC_NLP_DISABLED;
02766       break;
02767    case DAHDI_EVENT_EC_NLP_ENABLED:
02768       res = ANALOG_EVENT_EC_NLP_ENABLED;
02769       break;
02770 #endif
02771    case DAHDI_EVENT_PULSEDIGIT:
02772       res = ANALOG_EVENT_PULSEDIGIT;
02773       break;
02774    case DAHDI_EVENT_DTMFDOWN:
02775       res = ANALOG_EVENT_DTMFDOWN;
02776       break;
02777    case DAHDI_EVENT_DTMFUP:
02778       res = ANALOG_EVENT_DTMFUP;
02779       break;
02780    default:
02781       switch(event & 0xFFFF0000) {
02782       case DAHDI_EVENT_PULSEDIGIT:
02783       case DAHDI_EVENT_DTMFDOWN:
02784       case DAHDI_EVENT_DTMFUP:
02785          /* The event includes a digit number in the low word.
02786           * Converting it to a 'enum analog_event' would remove
02787           * that information. Thus it is returned as-is.
02788           */
02789          return event;
02790       }
02791 
02792       res = ANALOG_EVENT_ERROR;
02793       break;
02794    }
02795 
02796    return res;
02797 }

static enum analog_sigtype dahdisig_to_analogsig ( int  sig  )  [static]

Definition at line 1569 of file chan_dahdi.c.

References ANALOG_SIG_EM, ANALOG_SIG_EM_E1, ANALOG_SIG_EMWINK, ANALOG_SIG_FEATB, ANALOG_SIG_FEATD, ANALOG_SIG_FEATDMF, ANALOG_SIG_FEATDMF_TA, ANALOG_SIG_FGC_CAMA, ANALOG_SIG_FGC_CAMAMF, ANALOG_SIG_FXOGS, ANALOG_SIG_FXOKS, ANALOG_SIG_FXOLS, ANALOG_SIG_FXSGS, ANALOG_SIG_FXSKS, ANALOG_SIG_FXSLS, ANALOG_SIG_SF, ANALOG_SIG_SF_FEATD, ANALOG_SIG_SF_FEATDMF, ANALOG_SIG_SFWINK, 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_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.

01570 {
01571    switch (sig) {
01572    case SIG_FXOLS:
01573       return ANALOG_SIG_FXOLS;
01574    case SIG_FXOGS:
01575       return ANALOG_SIG_FXOGS;
01576    case SIG_FXOKS:
01577       return ANALOG_SIG_FXOKS;
01578    case SIG_FXSLS:
01579       return ANALOG_SIG_FXSLS;
01580    case SIG_FXSGS:
01581       return ANALOG_SIG_FXSGS;
01582    case SIG_FXSKS:
01583       return ANALOG_SIG_FXSKS;
01584    case SIG_EMWINK:
01585       return ANALOG_SIG_EMWINK;
01586    case SIG_EM:
01587       return ANALOG_SIG_EM;
01588    case SIG_EM_E1:
01589       return ANALOG_SIG_EM_E1;
01590    case SIG_FEATD:
01591       return ANALOG_SIG_FEATD;
01592    case SIG_FEATDMF:
01593       return ANALOG_SIG_FEATDMF;
01594    case SIG_E911:
01595       return SIG_E911;
01596    case SIG_FGC_CAMA:
01597       return ANALOG_SIG_FGC_CAMA;
01598    case SIG_FGC_CAMAMF:
01599       return ANALOG_SIG_FGC_CAMAMF;
01600    case SIG_FEATB:
01601       return ANALOG_SIG_FEATB;
01602    case SIG_SFWINK:
01603       return ANALOG_SIG_SFWINK;
01604    case SIG_SF:
01605       return ANALOG_SIG_SF;
01606    case SIG_SF_FEATD:
01607       return ANALOG_SIG_SF_FEATD;
01608    case SIG_SF_FEATDMF:
01609       return ANALOG_SIG_SF_FEATDMF;
01610    case SIG_FEATDMF_TA:
01611       return ANALOG_SIG_FEATDMF_TA;
01612    case SIG_SF_FEATB:
01613       return ANALOG_SIG_FEATB;
01614    default:
01615       return -1;
01616    }
01617 }

static void deep_copy_dahdi_chan_conf ( struct dahdi_chan_conf dest,
const struct dahdi_chan_conf src 
) [static]

Definition at line 17945 of file chan_dahdi.c.

References ast_cc_copy_config_params(), dahdi_pvt::cc_params, and dahdi_chan_conf::chan.

Referenced by setup_dahdi_int().

17946 {
17947    struct ast_cc_config_params *cc_params;
17948 
17949    cc_params = dest->chan.cc_params;
17950    *dest = *src;
17951    dest->chan.cc_params = cc_params;
17952    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
17953 }

static void destroy_all_channels ( void   )  [static]

Definition at line 5771 of file chan_dahdi.c.

References ast_db_del(), ast_db_get(), ast_mutex_lock, ast_mutex_unlock, ast_verb, dahdi_pvt::channel, dahdi_db, destroy_dahdi_pvt(), ifcount, iflist, iflock, sig_pri_span::lock, sig_pri_span::no_b_chan_iflist, num_restart_pending, NUM_SPANS, dahdi_pri::pri, dahdi_pvt::pri, sig_pri_span::pri, pris, dahdi_pvt::span, and SRVST_DBKEY.

Referenced by __unload_module().

05772 {
05773    int chan;
05774 #if defined(HAVE_PRI)
05775    unsigned span;
05776    struct sig_pri_span *pri;
05777 #endif   /* defined(HAVE_PRI) */
05778    struct dahdi_pvt *p;
05779 
05780    while (num_restart_pending) {
05781       usleep(1);
05782    }
05783 
05784    ast_mutex_lock(&iflock);
05785    /* Destroy all the interfaces and free their memory */
05786    while (iflist) {
05787       p = iflist;
05788 
05789       chan = p->channel;
05790 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05791       {
05792          char db_chan_name[20];
05793          char db_answer[5];
05794          char state;
05795          int why = -1;
05796 
05797          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05798          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05799             sscanf(db_answer, "%1c:%30d", &state, &why);
05800          }
05801          if (!why) {
05802             /* SRVST persistence is not required */
05803             ast_db_del(db_chan_name, SRVST_DBKEY);
05804          }
05805       }
05806 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05807       /* Free associated memory */
05808       destroy_dahdi_pvt(p);
05809       ast_verb(3, "Unregistered channel %d\n", chan);
05810    }
05811    ifcount = 0;
05812    ast_mutex_unlock(&iflock);
05813 
05814 #if defined(HAVE_PRI)
05815    /* Destroy all of the no B channel interface lists */
05816    for (span = 0; span < NUM_SPANS; ++span) {
05817       if (!pris[span].dchannels[0]) {
05818          break;
05819       }
05820       pri = &pris[span].pri;
05821       ast_mutex_lock(&pri->lock);
05822       while (pri->no_b_chan_iflist) {
05823          p = pri->no_b_chan_iflist;
05824 
05825          /* Free associated memory */
05826          destroy_dahdi_pvt(p);
05827       }
05828       ast_mutex_unlock(&pri->lock);
05829    }
05830 #endif   /* defined(HAVE_PRI) */
05831 }

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

Definition at line 5753 of file chan_dahdi.c.

References dahdi_subchannel::owner, dahdi_pvt::owner, and dahdi_pvt::subs.

Referenced by dahdi_destroy_channel_bynum(), and dahdi_hangup().

05754 {
05755    int i;
05756 
05757    if (!now) {
05758       /* Do not destroy the channel now if it is owned by someone. */
05759       if (cur->owner) {
05760          return;
05761       }
05762       for (i = 0; i < 3; i++) {
05763          if (cur->subs[i].owner) {
05764             return;
05765          }
05766       }
05767    }
05768    destroy_dahdi_pvt(cur);
05769 }

static void destroy_dahdi_pvt ( struct dahdi_pvt pvt  )  [static]

Definition at line 5683 of file chan_dahdi.c.

References analog_delete(), analog_lib_handles(), ast_cc_config_params_destroy(), ast_event_unsubscribe(), ast_free, ast_mutex_destroy, ast_smdi_interface_unref(), ast_variables_destroy(), dahdi_pvt::cc_params, dahdi_pvt::cidspill, dahdi_close_sub(), dahdi_iflist_extract(), DAHDI_IFLIST_MAIN, DAHDI_IFLIST_NO_B_CHAN, DAHDI_IFLIST_NONE, dahdi_nobch_extract(), dahdi_unlink_pri_pvt(), dahdi_unlink_ss7_pvt(), find_next_iface_in_span(), dahdi_pvt::lock, dahdi_pvt::manages_span_alarms, dahdi_pvt::mwi_event_sub, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::sig, sig_pri_chan_delete(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_chan_delete(), dahdi_pvt::smdi_iface, SUB_REAL, ast_channel::tech_pvt, dahdi_pvt::use_smdi, dahdi_pvt::vars, and dahdi_pvt::which_iflist.

Referenced by destroy_all_channels(), and duplicate_pseudo().

05684 {
05685    struct dahdi_pvt *p = pvt;
05686 
05687    if (p->manages_span_alarms) {
05688       struct dahdi_pvt *next = find_next_iface_in_span(p);
05689       if (next) {
05690          next->manages_span_alarms = 1;
05691       }
05692    }
05693 
05694    /* Remove channel from the list */
05695 #if defined(HAVE_PRI)
05696    dahdi_unlink_pri_pvt(p);
05697 #endif   /* defined(HAVE_PRI) */
05698 #if defined(HAVE_SS7)
05699    dahdi_unlink_ss7_pvt(p);
05700 #endif   /* defined(HAVE_SS7) */
05701    switch (pvt->which_iflist) {
05702    case DAHDI_IFLIST_NONE:
05703       break;
05704    case DAHDI_IFLIST_MAIN:
05705       dahdi_iflist_extract(p);
05706       break;
05707 #if defined(HAVE_PRI)
05708    case DAHDI_IFLIST_NO_B_CHAN:
05709       if (p->pri) {
05710          dahdi_nobch_extract(p->pri, p);
05711       }
05712       break;
05713 #endif   /* defined(HAVE_PRI) */
05714    }
05715 
05716    if (p->sig_pvt) {
05717       if (analog_lib_handles(p->sig, 0, 0)) {
05718          analog_delete(p->sig_pvt);
05719       }
05720       switch (p->sig) {
05721 #if defined(HAVE_PRI)
05722       case SIG_PRI_LIB_HANDLE_CASES:
05723          sig_pri_chan_delete(p->sig_pvt);
05724          break;
05725 #endif   /* defined(HAVE_PRI) */
05726 #if defined(HAVE_SS7)
05727       case SIG_SS7:
05728          sig_ss7_chan_delete(p->sig_pvt);
05729          break;
05730 #endif   /* defined(HAVE_SS7) */
05731       default:
05732          break;
05733       }
05734    }
05735    ast_free(p->cidspill);
05736    if (p->use_smdi)
05737       ast_smdi_interface_unref(p->smdi_iface);
05738    if (p->mwi_event_sub)
05739       ast_event_unsubscribe(p->mwi_event_sub);
05740    if (p->vars) {
05741       ast_variables_destroy(p->vars);
05742    }
05743    if (p->cc_params) {
05744       ast_cc_config_params_destroy(p->cc_params);
05745    }
05746    ast_mutex_destroy(&p->lock);
05747    dahdi_close_sub(p, SUB_REAL);
05748    if (p->owner)
05749       p->owner->tech_pvt = NULL;
05750    ast_free(p);
05751 }

static struct dahdi_pvt* determine_starting_point ( const char *  data,
struct dahdi_starting_point param 
) [static]

Definition at line 13356 of file chan_dahdi.c.

References args, ARRAY_LEN, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), CHAN_PSEUDO, errno, ifend, iflist, dahdi_pvt::next, dahdi_pvt::prev, and round_robin.

Referenced by dahdi_cc_callback(), and dahdi_request().

13357 {
13358    char *dest;
13359    char *s;
13360    int x;
13361    int res = 0;
13362    struct dahdi_pvt *p;
13363    char *subdir = NULL;
13364    AST_DECLARE_APP_ARGS(args,
13365       AST_APP_ARG(group);  /* channel/group token */
13366       //AST_APP_ARG(ext);  /* extension token */
13367       //AST_APP_ARG(opts); /* options token */
13368       AST_APP_ARG(other);  /* Any remining unused arguments */
13369    );
13370 
13371    /*
13372     * data is ---v
13373     * Dial(DAHDI/pseudo[/extension[/options]])
13374     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13375     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13376     * Dial(DAHDI/i<span>[/extension[/options]])
13377     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13378     *
13379     * i - ISDN span channel restriction.
13380     *     Used by CC to ensure that the CC recall goes out the same span.
13381     *     Also to make ISDN channel names dialable when the sequence number
13382     *     is stripped off.  (Used by DTMF attended transfer feature.)
13383     *
13384     * g - channel group allocation search forward
13385     * G - channel group allocation search backward
13386     * r - channel group allocation round robin search forward
13387     * R - channel group allocation round robin search backward
13388     *
13389     * c - Wait for DTMF digit to confirm answer
13390     * r<cadance#> - Set distintive ring cadance number
13391     * d - Force bearer capability for ISDN/SS7 call to digital.
13392     */
13393 
13394    if (data) {
13395       dest = ast_strdupa(data);
13396    } else {
13397       ast_log(LOG_WARNING, "Channel requested with no data\n");
13398       return NULL;
13399    }
13400    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13401    if (!args.argc || ast_strlen_zero(args.group)) {
13402       ast_log(LOG_WARNING, "No channel/group specified\n");
13403       return NULL;
13404    }
13405 
13406    /* Initialize the output parameters */
13407    memset(param, 0, sizeof(*param));
13408    param->channelmatch = -1;
13409 
13410    if (strchr(args.group, '!') != NULL) {
13411       char *prev = args.group;
13412       while ((s = strchr(prev, '!')) != NULL) {
13413          *s++ = '/';
13414          prev = s;
13415       }
13416       *(prev - 1) = '\0';
13417       subdir = args.group;
13418       args.group = prev;
13419    } else if (args.group[0] == 'i') {
13420       /* Extract the ISDN span channel restriction specifier. */
13421       res = sscanf(args.group + 1, "%30d", &x);
13422       if (res < 1) {
13423          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13424          return NULL;
13425       }
13426       param->span = x;
13427 
13428       /* Remove the ISDN span channel restriction specifier. */
13429       s = strchr(args.group, '-');
13430       if (!s) {
13431          /* Search all groups since we are ISDN span restricted. */
13432          return iflist;
13433       }
13434       args.group = s + 1;
13435       res = 0;
13436    }
13437    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13438       /* Retrieve the group number */
13439       s = args.group + 1;
13440       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13441       if (res < 1) {
13442          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13443          return NULL;
13444       }
13445       param->groupmatch = ((ast_group_t) 1 << x);
13446 
13447       if (toupper(args.group[0]) == 'G') {
13448          if (args.group[0] == 'G') {
13449             param->backwards = 1;
13450             p = ifend;
13451          } else
13452             p = iflist;
13453       } else {
13454          if (ARRAY_LEN(round_robin) <= x) {
13455             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13456                x, data);
13457             return NULL;
13458          }
13459          if (args.group[0] == 'R') {
13460             param->backwards = 1;
13461             p = round_robin[x] ? round_robin[x]->prev : ifend;
13462             if (!p)
13463                p = ifend;
13464          } else {
13465             p = round_robin[x] ? round_robin[x]->next : iflist;
13466             if (!p)
13467                p = iflist;
13468          }
13469          param->roundrobin = 1;
13470          param->rr_starting_point = x;
13471       }
13472    } else {
13473       s = args.group;
13474       if (!strcasecmp(s, "pseudo")) {
13475          /* Special case for pseudo */
13476          x = CHAN_PSEUDO;
13477          param->channelmatch = x;
13478       } else {
13479          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13480          if (res < 1) {
13481             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13482             return NULL;
13483          } else {
13484             param->channelmatch = x;
13485          }
13486       }
13487       if (subdir) {
13488          char path[PATH_MAX];
13489          struct stat stbuf;
13490 
13491          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13492                subdir, param->channelmatch);
13493          if (stat(path, &stbuf) < 0) {
13494             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13495                   path, strerror(errno));
13496             return NULL;
13497          }
13498          if (!S_ISCHR(stbuf.st_mode)) {
13499             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13500                   path);
13501             return NULL;
13502          }
13503          param->channelmatch = minor(stbuf.st_rdev);
13504       }
13505 
13506       p = iflist;
13507    }
13508 
13509    if (param->opt == 'r' && res < 3) {
13510       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13511       param->opt = '\0';
13512    }
13513 
13514    return p;
13515 }

static int device2chan ( const char *  subdir,
int  channel,
char *  path,
int  pathlen 
) [static]

Definition at line 12132 of file chan_dahdi.c.

References ast_log(), errno, LOG_DEBUG, and LOG_ERROR.

Referenced by build_channels().

12133 {
12134    struct stat stbuf;
12135    int      num;
12136 
12137    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12138    if (stat(path, &stbuf) < 0) {
12139       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12140       return -errno;
12141    }
12142    if (!S_ISCHR(stbuf.st_mode)) {
12143       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12144       return -EINVAL;
12145    }
12146    num = minor(stbuf.st_rdev);
12147    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12148    return num;
12149 
12150 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 4385 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

04386 {
04387    if (isdigit(digit))
04388       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04389    else if (digit >= 'A' && digit <= 'D')
04390       return DAHDI_TONE_DTMF_A + (digit - 'A');
04391    else if (digit >= 'a' && digit <= 'd')
04392       return DAHDI_TONE_DTMF_A + (digit - 'a');
04393    else if (digit == '*')
04394       return DAHDI_TONE_DTMF_s;
04395    else if (digit == '#')
04396       return DAHDI_TONE_DTMF_p;
04397    else
04398       return -1;
04399 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 6574 of file chan_dahdi.c.

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

Referenced by dahdi_bridge(), and dahdi_setoption().

06575 {
06576    int val = 0;
06577 
06578    p->ignoredtmf = 1;
06579 
06580    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06581 
06582    if (!p->hardwaredtmf && p->dsp) {
06583       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06584       ast_dsp_set_features(p->dsp, p->dsp_features);
06585    }
06586 }

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

Definition at line 11557 of file chan_dahdi.c.

References analog_lib_handles(), ast_calloc, ast_debug, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, dahdi_pvt::cidspill, ifcount, iflist, iflock, last, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwisendactive, dahdi_pvt::next, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.

Referenced by restart_monitor().

11558 {
11559    int count, res, res2, spoint, pollres=0;
11560    struct dahdi_pvt *i;
11561    struct dahdi_pvt *last = NULL;
11562    struct dahdi_pvt *doomed;
11563    time_t thispass = 0, lastpass = 0;
11564    int found;
11565    char buf[1024];
11566    struct pollfd *pfds=NULL;
11567    int lastalloc = -1;
11568    /* This thread monitors all the frame relay interfaces which are not yet in use
11569       (and thus do not have a separate thread) indefinitely */
11570    /* From here on out, we die whenever asked */
11571 #if 0
11572    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11573       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11574       return NULL;
11575    }
11576    ast_debug(1, "Monitor starting...\n");
11577 #endif
11578    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11579 
11580    for (;;) {
11581       /* Lock the interface list */
11582       ast_mutex_lock(&iflock);
11583       if (!pfds || (lastalloc != ifcount)) {
11584          if (pfds) {
11585             ast_free(pfds);
11586             pfds = NULL;
11587          }
11588          if (ifcount) {
11589             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11590                ast_mutex_unlock(&iflock);
11591                return NULL;
11592             }
11593          }
11594          lastalloc = ifcount;
11595       }
11596       /* Build the stuff we're going to poll on, that is the socket of every
11597          dahdi_pvt that does not have an associated owner channel */
11598       count = 0;
11599       for (i = iflist; i; i = i->next) {
11600          ast_mutex_lock(&i->lock);
11601          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11602             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11603                struct analog_pvt *p = i->sig_pvt;
11604 
11605                if (!p)
11606                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11607 
11608                if (!p->owner && !p->subs[SUB_REAL].owner) {
11609                   /* This needs to be watched, as it lacks an owner */
11610                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11611                   pfds[count].events = POLLPRI;
11612                   pfds[count].revents = 0;
11613                   /* Message waiting or r2 channels also get watched for reading */
11614                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11615                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11616                      pfds[count].events |= POLLIN;
11617                   }
11618                   count++;
11619                }
11620             } else {
11621                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11622                   /* This needs to be watched, as it lacks an owner */
11623                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11624                   pfds[count].events = POLLPRI;
11625                   pfds[count].revents = 0;
11626                   /* If we are monitoring for VMWI or sending CID, we need to
11627                      read from the channel as well */
11628                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11629                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11630                      pfds[count].events |= POLLIN;
11631                   }
11632                   count++;
11633                }
11634             }
11635          }
11636          ast_mutex_unlock(&i->lock);
11637       }
11638       /* Okay, now that we know what to do, release the interface lock */
11639       ast_mutex_unlock(&iflock);
11640 
11641       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11642       pthread_testcancel();
11643       /* Wait at least a second for something to happen */
11644       res = poll(pfds, count, 1000);
11645       pthread_testcancel();
11646       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11647 
11648       /* Okay, poll has finished.  Let's see what happened.  */
11649       if (res < 0) {
11650          if ((errno != EAGAIN) && (errno != EINTR))
11651             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11652          continue;
11653       }
11654       /* Alright, lock the interface list again, and let's look and see what has
11655          happened */
11656       ast_mutex_lock(&iflock);
11657       found = 0;
11658       spoint = 0;
11659       lastpass = thispass;
11660       thispass = time(NULL);
11661       doomed = NULL;
11662       for (i = iflist;; i = i->next) {
11663          if (doomed) {
11664             int res;
11665             res = dahdi_destroy_channel_bynum(doomed->channel);
11666             if (res != RESULT_SUCCESS) {
11667                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11668             }
11669             doomed = NULL;
11670          }
11671          if (!i) {
11672             break;
11673          }
11674 
11675          if (thispass != lastpass) {
11676             if (!found && ((i == last) || ((i == iflist) && !last))) {
11677                last = i;
11678                if (last) {
11679                   struct analog_pvt *analog_p = last->sig_pvt;
11680                   /* Only allow MWI to be initiated on a quiescent fxs port */
11681                   if (analog_p
11682                      && !last->mwisendactive
11683                      && (last->sig & __DAHDI_SIG_FXO)
11684                      && !analog_p->fxsoffhookstate
11685                      && !last->owner
11686                      && !ast_strlen_zero(last->mailbox)
11687                      && (thispass - analog_p->onhooktime > 3)) {
11688                      res = has_voicemail(last);
11689                      if (analog_p->msgstate != res) {
11690                         /* Set driver resources for signalling VMWI */
11691                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11692                         if (res2) {
11693                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11694                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11695                         }
11696                         /* If enabled for FSK spill then initiate it */
11697                         if (mwi_send_init(last)) {
11698                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11699                         }
11700                         analog_p->msgstate = res;
11701                         found ++;
11702                      }
11703                   }
11704                   last = last->next;
11705                }
11706             }
11707          }
11708          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11709             if (i->radio && !i->owner)
11710             {
11711                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11712                if (res)
11713                {
11714                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11715                   /* Don't hold iflock while handling init events */
11716                   ast_mutex_unlock(&iflock);
11717                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11718                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11719                   else
11720                      doomed = handle_init_event(i, res);
11721                   ast_mutex_lock(&iflock);
11722                }
11723                continue;
11724             }
11725             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11726             if (pollres & POLLIN) {
11727                if (i->owner || i->subs[SUB_REAL].owner) {
11728 #ifdef HAVE_PRI
11729                   if (!i->pri)
11730 #endif
11731                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11732                   continue;
11733                }
11734                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11735                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11736                   continue;
11737                }
11738                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11739                if (res > 0) {
11740                   if (i->mwimonitor_fsk) {
11741                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11742                         pthread_attr_t attr;
11743                         pthread_t threadid;
11744                         struct mwi_thread_data *mtd;
11745 
11746                         pthread_attr_init(&attr);
11747                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11748 
11749                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11750                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11751                            mtd->pvt = i;
11752                            memcpy(mtd->buf, buf, res);
11753                            mtd->len = res;
11754                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11755                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11756                               ast_free(mtd);
11757                            }
11758                            i->mwimonitoractive = 1;
11759                         }
11760                      }
11761                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11762                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11763                      int energy;
11764                      struct timeval now;
11765                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11766                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11767                      */
11768                      if (1 == i->dtmfcid_holdoff_state) {
11769                         gettimeofday(&i->dtmfcid_delay, NULL);
11770                         i->dtmfcid_holdoff_state = 2;
11771                      } else if (2 == i->dtmfcid_holdoff_state) {
11772                         gettimeofday(&now, NULL);
11773                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11774                            i->dtmfcid_holdoff_state = 0;
11775                         }
11776                      } else {
11777                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11778                         if (!i->mwisendactive && energy > dtmfcid_level) {
11779                            pthread_t threadid;
11780                            struct ast_channel *chan;
11781                            ast_mutex_unlock(&iflock);
11782                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11783                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11784                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11785                               i->dtmfcid_holdoff_state = 1;
11786                            } else {
11787                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11788                               if (!chan) {
11789                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11790                               } else {
11791                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11792                                  if (res) {
11793                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11794                                  } else {
11795                                     i->dtmfcid_holdoff_state = 1;
11796                                  }
11797                               }
11798                            }
11799                            ast_mutex_lock(&iflock);
11800                         }
11801                      }
11802                   }
11803                   if (i->mwisendactive) {
11804                      mwi_send_process_buffer(i, res);
11805                   }
11806                } else {
11807                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11808                }
11809             }
11810             if (pollres & POLLPRI) {
11811                if (i->owner || i->subs[SUB_REAL].owner) {
11812 #ifdef HAVE_PRI
11813                   if (!i->pri)
11814 #endif
11815                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11816                   continue;
11817                }
11818                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11819                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11820                /* Don't hold iflock while handling init events */
11821                ast_mutex_unlock(&iflock);
11822                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11823                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11824                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11825                   else
11826                      doomed = handle_init_event(i, res);
11827                }
11828                ast_mutex_lock(&iflock);
11829             }
11830          }
11831       }
11832       ast_mutex_unlock(&iflock);
11833    }
11834    /* Never reached */
11835    return NULL;
11836 
11837 }

static int drc_sample ( int  sample,
float  drc 
) [static]

Definition at line 4924 of file chan_dahdi.c.

Referenced by fill_rxgain(), and fill_txgain().

04925 {
04926    float neg;
04927    float shallow, steep;
04928    float max = SHRT_MAX;
04929    
04930    neg = (sample < 0 ? -1 : 1);
04931    steep = drc*sample;
04932    shallow = neg*(max-max/drc)+(float)sample/drc;
04933    if (abs(steep) < abs(shallow)) {
04934       sample = steep;
04935    }
04936    else {
04937       sample = shallow;
04938    }
04939 
04940    return sample;
04941 }

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

Definition at line 13292 of file chan_dahdi.c.

References ast_cc_config_params_init, ast_cc_copy_config_params(), ast_free, ast_log(), ast_malloc, ast_mutex_init, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::cc_params, dahdi_iflist_insert(), DAHDI_IFLIST_NONE, dahdi_open(), destroy_dahdi_pvt(), errno, and SUB_REAL.

Referenced by dahdi_request().

13293 {
13294    struct dahdi_pvt *p;
13295    struct dahdi_bufferinfo bi;
13296    int res;
13297 
13298    p = ast_malloc(sizeof(*p));
13299    if (!p) {
13300       return NULL;
13301    }
13302    *p = *src;
13303 
13304    /* Must deep copy the cc_params. */
13305    p->cc_params = ast_cc_config_params_init();
13306    if (!p->cc_params) {
13307       ast_free(p);
13308       return NULL;
13309    }
13310    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13311 
13312    p->which_iflist = DAHDI_IFLIST_NONE;
13313    p->next = NULL;
13314    p->prev = NULL;
13315    ast_mutex_init(&p->lock);
13316    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13317    if (p->subs[SUB_REAL].dfd < 0) {
13318       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13319       destroy_dahdi_pvt(p);
13320       return NULL;
13321    }
13322    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13323    if (!res) {
13324       bi.txbufpolicy = src->buf_policy;
13325       bi.rxbufpolicy = src->buf_policy;
13326       bi.numbufs = src->buf_no;
13327       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13328       if (res < 0) {
13329          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13330       }
13331    } else
13332       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13333    p->destroy = 1;
13334    dahdi_iflist_insert(p);
13335    return p;
13336 }

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 6588 of file chan_dahdi.c.

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

Referenced by dahdi_bridge(), and dahdi_setoption().

06589 {
06590    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06591 
06592    if (p->channel == CHAN_PSEUDO)
06593       return;
06594 
06595    p->ignoredtmf = 0;
06596 
06597    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06598 
06599    if (!p->hardwaredtmf && p->dsp) {
06600       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06601       ast_dsp_set_features(p->dsp, p->dsp_features);
06602    }
06603 }

static const char * event2str ( int  event  )  [static]

Definition at line 4537 of file chan_dahdi.c.

References ARRAY_LEN.

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_handle_event(), mwi_thread(), my_distinctive_ring(), my_handle_dchan_exception(), and my_handle_link_exception().

04538 {
04539    static char buf[256];
04540    if ((event < (ARRAY_LEN(events))) && (event > -1))
04541       return events[event];
04542    sprintf(buf, "Event %d", event); /* safe */
04543    return buf;
04544 }

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

Definition at line 4988 of file chan_dahdi.c.

References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, AST_MULAW, and drc_sample().

Referenced by set_actual_rxgain().

04989 {
04990    int j;
04991    int k;
04992    float linear_gain = pow(10.0, gain / 20.0);
04993 
04994    switch (law) {
04995    case DAHDI_LAW_ALAW:
04996       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04997          if (gain || drc) {
04998             k = AST_ALAW(j);
04999             if (drc) {
05000                k = drc_sample(k, drc);
05001             }
05002             k = (float)k*linear_gain;
05003             if (k > 32767) k = 32767;
05004             if (k < -32767) k = -32767;
05005             g->rxgain[j] = AST_LIN2A(k);
05006          } else {
05007             g->rxgain[j] = j;
05008          }
05009       }
05010       break;
05011    case DAHDI_LAW_MULAW:
05012       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05013          if (gain || drc) {
05014             k = AST_MULAW(j);
05015             if (drc) {
05016                k = drc_sample(k, drc);
05017             }
05018             k = (float)k*linear_gain;
05019             if (k > 32767) k = 32767;
05020             if (k < -32767) k = -32767;
05021             g->rxgain[j] = AST_LIN2MU(k);
05022          } else {
05023             g->rxgain[j] = j;
05024          }
05025       }
05026       break;
05027    }
05028 }

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

Definition at line 4944 of file chan_dahdi.c.

References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, AST_MULAW, and drc_sample().

Referenced by set_actual_txgain().

04945 {
04946    int j;
04947    int k;
04948 
04949    float linear_gain = pow(10.0, gain / 20.0);
04950 
04951    switch (law) {
04952    case DAHDI_LAW_ALAW:
04953       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04954          if (gain || drc) {
04955             k = AST_ALAW(j);
04956             if (drc) {
04957                k = drc_sample(k, drc);
04958             }
04959             k = (float)k*linear_gain;
04960             if (k > 32767) k = 32767;
04961             if (k < -32767) k = -32767;
04962             g->txgain[j] = AST_LIN2A(k);
04963          } else {
04964             g->txgain[j] = j;
04965          }
04966       }
04967       break;
04968    case DAHDI_LAW_MULAW:
04969       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04970          if (gain || drc) {
04971             k = AST_MULAW(j);
04972             if (drc) {
04973                k = drc_sample(k, drc);
04974             }
04975             k = (float)k*linear_gain;
04976             if (k > 32767) k = 32767;
04977             if (k < -32767) k = -32767;
04978             g->txgain[j] = AST_LIN2MU(k);
04979 
04980          } else {
04981             g->txgain[j] = j;
04982          }
04983       }
04984       break;
04985    }
04986 }

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

Definition at line 15767 of file chan_dahdi.c.

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

Referenced by find_channel_from_str().

15768 {
15769    struct dahdi_pvt *p;
15770 
15771    ast_mutex_lock(&iflock);
15772    for (p = iflist; p; p = p->next) {
15773       if (p->channel == channel) {
15774          break;
15775       }
15776    }
15777    ast_mutex_unlock(&iflock);
15778    return p;
15779 }

static struct dahdi_pvt* find_channel_from_str ( const char *  channel  )  [static]

Definition at line 15790 of file chan_dahdi.c.

References find_channel().

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

15791 {
15792    int chan_num;
15793 
15794    if (sscanf(channel, "%30d", &chan_num) != 1) {
15795       /* Not numeric string. */
15796       return NULL;
15797    }
15798 
15799    return find_channel(chan_num);
15800 }

static struct dahdi_pvt* find_next_iface_in_span ( struct dahdi_pvt cur  )  [static]

Definition at line 5672 of file chan_dahdi.c.

References dahdi_pvt::next, dahdi_pvt::prev, and dahdi_pvt::span.

Referenced by destroy_dahdi_pvt().

05673 {
05674    if (cur->next && cur->next->span == cur->span) {
05675       return cur->next;
05676    } else if (cur->prev && cur->prev->span == cur->span) {
05677       return cur->prev;
05678    }
05679 
05680    return NULL;
05681 }

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

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

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

07659 {
07660    int res;
07661    struct dahdi_spaninfo zi;
07662    struct dahdi_params params;
07663 
07664    memset(&zi, 0, sizeof(zi));
07665    zi.spanno = p->span;
07666 
07667    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07668       if (zi.alarms != DAHDI_ALARM_NONE)
07669          return zi.alarms;
07670    } else {
07671       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07672       return 0;
07673    }
07674 
07675    /* No alarms on the span. Check for channel alarms. */
07676    memset(&params, 0, sizeof(params));
07677    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07678       return params.chan_alarms;
07679 
07680    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07681 
07682    return DAHDI_ALARM_NONE;
07683 }

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

Definition at line 7783 of file chan_dahdi.c.

References alarm2str(), ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, manager_event, dahdi_pvt::manages_span_alarms, report_alarms, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, and dahdi_pvt::span.

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

07784 {
07785    const char *alarm_str = alarm2str(alms);
07786 
07787    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07788       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07789       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07790                  "Alarm: %s\r\n"
07791                  "Channel: %d\r\n",
07792                  alarm_str, p->channel);
07793    }
07794 
07795    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07796       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07797       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07798                  "Alarm: %s\r\n"
07799                  "Span: %d\r\n",
07800                  alarm_str, p->span);
07801    }
07802 }

static void handle_clear_alarms ( struct dahdi_pvt p  )  [static]

Definition at line 3760 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, LOG_NOTICE, manager_event, dahdi_pvt::manages_span_alarms, report_alarms, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, and dahdi_pvt::span.

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

03761 {
03762    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03763       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03764       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03765    }
03766    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03767       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03768       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03769    }
03770 }

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

Definition at line 15385 of file chan_dahdi.c.

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

15386 {
15387    int i, j;
15388    switch (cmd) {
15389    case CLI_INIT:
15390       e->command = "dahdi show cadences";
15391       e->usage =
15392          "Usage: dahdi show cadences\n"
15393          "       Shows all cadences currently defined\n";
15394       return NULL;
15395    case CLI_GENERATE:
15396       return NULL;
15397    }
15398    for (i = 0; i < num_cadence; i++) {
15399       char output[1024];
15400       char tmp[16], tmp2[64];
15401       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15402       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15403 
15404       for (j = 0; j < 16; j++) {
15405          if (cadences[i].ringcadence[j] == 0)
15406             break;
15407          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15408          if (cidrings[i] * 2 - 1 == j)
15409             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15410          else
15411             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15412          if (j != 0)
15413             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15414          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15415       }
15416       ast_cli(a->fd,"%s\n",output);
15417    }
15418    return CLI_SUCCESS;
15419 }

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

Definition at line 11311 of file chan_dahdi.c.

References analog_ss_thread(), ast_free, ast_hangup(), ast_log(), ast_mutex_lock, ast_mutex_unlock, 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(), errno, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pvt::lock, LOG_NOTICE, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_neon, notify_message(), dahdi_pvt::polarity, POLARITY_REV, dahdi_pvt::radio, restore_conference(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, 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_chan_alarm_notify(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sig_ss7_set_alarm(), SUB_REAL, and dahdi_pvt::subs.

11312 {
11313    int res;
11314    pthread_t threadid;
11315    struct ast_channel *chan;
11316 
11317    /* Handle an event on a given channel for the monitor thread. */
11318 
11319    switch (event) {
11320    case DAHDI_EVENT_NONE:
11321    case DAHDI_EVENT_BITSCHANGED:
11322       break;
11323    case DAHDI_EVENT_WINKFLASH:
11324    case DAHDI_EVENT_RINGOFFHOOK:
11325       if (i->inalarm) break;
11326       if (i->radio) break;
11327       /* Got a ring/answer.  What kind of channel are we? */
11328       switch (i->sig) {
11329       case SIG_FXOLS:
11330       case SIG_FXOGS:
11331       case SIG_FXOKS:
11332          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11333          if (res && (errno == EBUSY))
11334             break;
11335 
11336          /* Cancel VMWI spill */
11337          ast_free(i->cidspill);
11338          i->cidspill = NULL;
11339          restore_conference(i);
11340 
11341          if (i->immediate) {
11342             dahdi_enable_ec(i);
11343             /* The channel is immediately up.  Start right away */
11344             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11345             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11346             if (!chan) {
11347                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11348                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11349                if (res < 0)
11350                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11351             }
11352          } else {
11353             /* Check for callerid, digits, etc */
11354             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11355             if (chan) {
11356                if (has_voicemail(i))
11357                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11358                else
11359                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11360                if (res < 0)
11361                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11362                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11363                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11364                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11365                   if (res < 0)
11366                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11367                   ast_hangup(chan);
11368                }
11369             } else
11370                ast_log(LOG_WARNING, "Unable to create channel\n");
11371          }
11372          break;
11373       case SIG_FXSLS:
11374       case SIG_FXSGS:
11375       case SIG_FXSKS:
11376             i->ringt = i->ringt_base;
11377             /* Fall through */
11378       case SIG_EMWINK:
11379       case SIG_FEATD:
11380       case SIG_FEATDMF:
11381       case SIG_FEATDMF_TA:
11382       case SIG_E911:
11383       case SIG_FGC_CAMA:
11384       case SIG_FGC_CAMAMF:
11385       case SIG_FEATB:
11386       case SIG_EM:
11387       case SIG_EM_E1:
11388       case SIG_SFWINK:
11389       case SIG_SF_FEATD:
11390       case SIG_SF_FEATDMF:
11391       case SIG_SF_FEATB:
11392       case SIG_SF:
11393          /* Check for callerid, digits, etc */
11394          if (i->cid_start == CID_START_POLARITY_IN) {
11395             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11396          } else {
11397             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11398          }
11399 
11400          if (!chan) {
11401             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11402          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11403             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11404             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11405             if (res < 0) {
11406                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11407             }
11408             ast_hangup(chan);
11409          }
11410          break;
11411       default:
11412          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11413          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11414          if (res < 0)
11415             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11416          return NULL;
11417       }
11418       break;
11419    case DAHDI_EVENT_NOALARM:
11420       switch (i->sig) {
11421 #if defined(HAVE_PRI)
11422       case SIG_PRI_LIB_HANDLE_CASES:
11423          ast_mutex_lock(&i->lock);
11424          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11425          ast_mutex_unlock(&i->lock);
11426          break;
11427 #endif   /* defined(HAVE_PRI) */
11428 #if defined(HAVE_SS7)
11429       case SIG_SS7:
11430          sig_ss7_set_alarm(i->sig_pvt, 0);
11431          break;
11432 #endif   /* defined(HAVE_SS7) */
11433       default:
11434          i->inalarm = 0;
11435          break;
11436       }
11437       handle_clear_alarms(i);
11438       break;
11439    case DAHDI_EVENT_ALARM:
11440       switch (i->sig) {
11441 #if defined(HAVE_PRI)
11442       case SIG_PRI_LIB_HANDLE_CASES:
11443          ast_mutex_lock(&i->lock);
11444          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11445          ast_mutex_unlock(&i->lock);
11446          break;
11447 #endif   /* defined(HAVE_PRI) */
11448 #if defined(HAVE_SS7)
11449       case SIG_SS7:
11450          sig_ss7_set_alarm(i->sig_pvt, 1);
11451          break;
11452 #endif   /* defined(HAVE_SS7) */
11453       default:
11454          i->inalarm = 1;
11455          break;
11456       }
11457       res = get_alarms(i);
11458       handle_alarms(i, res);
11459       /* fall thru intentionally */
11460    case DAHDI_EVENT_ONHOOK:
11461       if (i->radio)
11462          break;
11463       /* Back on hook.  Hang up. */
11464       switch (i->sig) {
11465       case SIG_FXOLS:
11466       case SIG_FXOGS:
11467       case SIG_FEATD:
11468       case SIG_FEATDMF:
11469       case SIG_FEATDMF_TA:
11470       case SIG_E911:
11471       case SIG_FGC_CAMA:
11472       case SIG_FGC_CAMAMF:
11473       case SIG_FEATB:
11474       case SIG_EM:
11475       case SIG_EM_E1:
11476       case SIG_EMWINK:
11477       case SIG_SF_FEATD:
11478       case SIG_SF_FEATDMF:
11479       case SIG_SF_FEATB:
11480       case SIG_SF:
11481       case SIG_SFWINK:
11482       case SIG_FXSLS:
11483       case SIG_FXSGS:
11484       case SIG_FXSKS:
11485       case SIG_FXOKS:
11486          dahdi_disable_ec(i);
11487          /* Diddle the battery for the zhone */
11488 #ifdef ZHONE_HACK
11489          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11490          usleep(1);
11491 #endif
11492          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11493          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11494          break;
11495       case SIG_SS7:
11496       case SIG_PRI_LIB_HANDLE_CASES:
11497          dahdi_disable_ec(i);
11498          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11499          break;
11500       default:
11501          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11502          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11503          return NULL;
11504       }
11505       break;
11506    case DAHDI_EVENT_POLARITY:
11507       switch (i->sig) {
11508       case SIG_FXSLS:
11509       case SIG_FXSKS:
11510       case SIG_FXSGS:
11511          /* We have already got a PR before the channel was
11512             created, but it wasn't handled. We need polarity
11513             to be REV for remote hangup detection to work.
11514             At least in Spain */
11515          if (i->hanguponpolarityswitch)
11516             i->polarity = POLARITY_REV;
11517          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11518             i->polarity = POLARITY_REV;
11519             ast_verb(2, "Starting post polarity "
11520                "CID detection on channel %d\n",
11521                i->channel);
11522             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11523             if (!chan) {
11524                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11525             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11526                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11527             }
11528          }
11529          break;
11530       default:
11531          ast_log(LOG_WARNING, "handle_init_event detected "
11532             "polarity reversal on non-FXO (SIG_FXS) "
11533             "interface %d\n", i->channel);
11534       }
11535       break;
11536    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11537       ast_log(LOG_NOTICE,
11538             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11539             i->channel);
11540       return i;
11541    case DAHDI_EVENT_NEONMWI_ACTIVE:
11542       if (i->mwimonitor_neon) {
11543          notify_message(i->mailbox, 1);
11544          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11545       }
11546       break;
11547    case DAHDI_EVENT_NEONMWI_INACTIVE:
11548       if (i->mwimonitor_neon) {
11549          notify_message(i->mailbox, 0);
11550          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11551       }
11552       break;
11553    }
11554    return NULL;
11555 }

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

Definition at line 14753 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_mutex_lock, dahdi_pvt::channel, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.

14754 {
14755    struct dahdi_pvt *p = NULL;
14756    int channo = 0;
14757    switch (cmd) {
14758    case CLI_INIT:
14759       e->command = "mfcr2 call files [on|off]";
14760       e->usage =
14761          "Usage: mfcr2 call files [on|off] <channel>\n"
14762          "       Enable call files creation on the specified channel.\n"
14763          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14764       return NULL;
14765    case CLI_GENERATE:
14766       return NULL;
14767    }
14768    if (a->argc < 4) {
14769       return CLI_SHOWUSAGE;
14770    }
14771    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14772    ast_mutex_lock(&iflock);
14773    for (p = iflist; p; p = p->next) {
14774       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14775          continue;
14776       }
14777       if ((channo != -1) && (p->channel != channo )) {
14778          continue;
14779       }
14780       if (ast_true(a->argv[3])) {
14781          openr2_chan_enable_call_files(p->r2chan);
14782       } else {
14783          openr2_chan_disable_call_files(p->r2chan);
14784       }
14785       if (channo != -1) {
14786          if (ast_true(a->argv[3])) {
14787             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14788          } else {
14789             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14790          }
14791          break;
14792       }
14793    }
14794    if ((channo != -1) && !p) {
14795       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14796    }
14797    if (channo == -1) {
14798       if (ast_true(a->argv[3])) {
14799          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14800       } else {
14801          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14802       }
14803    }
14804    ast_mutex_unlock(&iflock);
14805    return CLI_SUCCESS;
14806 }

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

Definition at line 14849 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_mutex_lock, dahdi_pvt::channel, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.

14850 {
14851    struct dahdi_pvt *p = NULL;
14852    int channo = 0;
14853    switch (cmd) {
14854    case CLI_INIT:
14855       e->command = "mfcr2 set blocked";
14856       e->usage =
14857          "Usage: mfcr2 set blocked <channel>\n"
14858          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14859          "       Force the given channel into BLOCKED state.\n"
14860          "       If no channel is specified, all channels will be set to BLOCKED.\n";
14861       return NULL;
14862    case CLI_GENERATE:
14863       return NULL;
14864    }
14865    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14866    ast_mutex_lock(&iflock);
14867    for (p = iflist; p; p = p->next) {
14868       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14869          continue;
14870       }
14871       if ((channo != -1) && (p->channel != channo )) {
14872          continue;
14873       }
14874       openr2_chan_set_blocked(p->r2chan);
14875       ast_mutex_lock(&p->lock);
14876       p->locallyblocked = 1;
14877       ast_mutex_unlock(&p->lock);
14878       if (channo != -1) {
14879          break;
14880       }
14881    }
14882    if ((channo != -1) && !p) {
14883       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14884    }
14885    ast_mutex_unlock(&iflock);
14886    return CLI_SUCCESS;
14887 }

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

Definition at line 14688 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_strdupa, dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, ast_cli_args::fd, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.

14689 {
14690    struct dahdi_pvt *p = NULL;
14691    int channo = 0;
14692    char *toklevel = NULL;
14693    char *saveptr = NULL;
14694    char *logval = NULL;
14695    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14696    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14697    switch (cmd) {
14698    case CLI_INIT:
14699       e->command = "mfcr2 set debug";
14700       e->usage =
14701          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14702          "       Set a new logging level for the specified channel.\n"
14703          "       If no channel is specified the logging level will be applied to all channels.\n";
14704       return NULL;
14705    case CLI_GENERATE:
14706       return NULL;
14707    }
14708    if (a->argc < 4) {
14709       return CLI_SHOWUSAGE;
14710    }
14711    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14712    logval = ast_strdupa(a->argv[3]);
14713    toklevel = strtok_r(logval, ",", &saveptr);
14714    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14715       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14716       return CLI_FAILURE;
14717    } else if (OR2_LOG_NOTHING == tmplevel) {
14718       loglevel = tmplevel;
14719    } else {
14720       loglevel |= tmplevel;
14721       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14722          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14723             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14724             continue;
14725          }
14726          loglevel |= tmplevel;
14727       }
14728    }
14729    ast_mutex_lock(&iflock);
14730    for (p = iflist; p; p = p->next) {
14731       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14732          continue;
14733       }
14734       if ((channo != -1) && (p->channel != channo )) {
14735          continue;
14736       }
14737       openr2_chan_set_log_level(p->r2chan, loglevel);
14738       if (channo != -1) {
14739          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14740          break;
14741       }
14742    }
14743    if ((channo != -1) && !p) {
14744       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14745    }
14746    if (channo == -1) {
14747       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14748    }
14749    ast_mutex_unlock(&iflock);
14750    return CLI_SUCCESS;
14751 }

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

Definition at line 14808 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_mutex_lock, dahdi_pvt::channel, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.

14809 {
14810    struct dahdi_pvt *p = NULL;
14811    int channo = 0;
14812    switch (cmd) {
14813    case CLI_INIT:
14814       e->command = "mfcr2 set idle";
14815       e->usage =
14816          "Usage: mfcr2 set idle <channel>\n"
14817          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14818          "       Force the given channel into IDLE state.\n"
14819          "       If no channel is specified, all channels will be set to IDLE.\n";
14820       return NULL;
14821    case CLI_GENERATE:
14822       return NULL;
14823    }
14824    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14825    ast_mutex_lock(&iflock);
14826    for (p = iflist; p; p = p->next) {
14827       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14828          continue;
14829       }
14830       if ((channo != -1) && (p->channel != channo )) {
14831          continue;
14832       }
14833       openr2_chan_set_idle(p->r2chan);
14834       ast_mutex_lock(&p->lock);
14835       p->locallyblocked = 0;
14836       p->mfcr2call = 0;
14837       ast_mutex_unlock(&p->lock);
14838       if (channo != -1) {
14839          break;
14840       }
14841    }
14842    if ((channo != -1) && !p) {
14843       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14844    }
14845    ast_mutex_unlock(&iflock);
14846    return CLI_SUCCESS;
14847 }

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

Definition at line 14614 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, dahdi_pvt::context, ast_cli_args::fd, FORMAT, dahdi_pvt::group, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.

14615 {
14616 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14617    int filtertype = 0;
14618    int targetnum = 0;
14619    char channo[5];
14620    char anino[5];
14621    char dnisno[5];
14622    struct dahdi_pvt *p;
14623    openr2_context_t *r2context;
14624    openr2_variant_t r2variant;
14625    switch (cmd) {
14626    case CLI_INIT:
14627       e->command = "mfcr2 show channels [group|context]";
14628       e->usage =
14629          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14630          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14631       return NULL;
14632    case CLI_GENERATE:
14633       return NULL;
14634    }
14635    if (!((a->argc == 3) || (a->argc == 5))) {
14636       return CLI_SHOWUSAGE;
14637    }
14638    if (a->argc == 5) {
14639       if (!strcasecmp(a->argv[3], "group")) {
14640          targetnum = atoi(a->argv[4]);
14641          if ((targetnum < 0) || (targetnum > 63))
14642             return CLI_SHOWUSAGE;
14643          targetnum = 1 << targetnum;
14644          filtertype = 1;
14645       } else if (!strcasecmp(a->argv[3], "context")) {
14646          filtertype = 2;
14647       } else {
14648          return CLI_SHOWUSAGE;
14649       }
14650    }
14651    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14652    ast_mutex_lock(&iflock);
14653    for (p = iflist; p; p = p->next) {
14654       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14655          continue;
14656       }
14657       if (filtertype) {
14658          switch(filtertype) {
14659          case 1: /* mfcr2 show channels group <group> */
14660             if (p->group != targetnum) {
14661                continue;
14662             }
14663             break;
14664          case 2: /* mfcr2 show channels context <context> */
14665             if (strcasecmp(p->context, a->argv[4])) {
14666                continue;
14667             }
14668             break;
14669          default:
14670             ;
14671          }
14672       }
14673       r2context = openr2_chan_get_context(p->r2chan);
14674       r2variant = openr2_context_get_variant(r2context);
14675       snprintf(channo, sizeof(channo), "%d", p->channel);
14676       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14677       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14678       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14679             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14680             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14681             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14682    }
14683    ast_mutex_unlock(&iflock);
14684    return CLI_SUCCESS;
14685 #undef FORMAT
14686 }

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

Definition at line 14586 of file chan_dahdi.c.

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

14587 {
14588 #define FORMAT "%4s %40s\n"
14589    int i = 0;
14590    int numvariants = 0;
14591    const openr2_variant_entry_t *variants;
14592    switch (cmd) {
14593    case CLI_INIT:
14594       e->command = "mfcr2 show variants";
14595       e->usage =
14596          "Usage: mfcr2 show variants\n"
14597          "       Shows the list of MFC/R2 variants supported.\n";
14598       return NULL;
14599    case CLI_GENERATE:
14600       return NULL;
14601    }
14602    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14603       ast_cli(a->fd, "Failed to get list of variants.\n");
14604       return CLI_FAILURE;
14605    }
14606    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14607    for (i = 0; i < numvariants; i++) {
14608       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14609    }
14610    return CLI_SUCCESS;
14611 #undef FORMAT
14612 }

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

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

14571 {
14572    switch (cmd) {
14573    case CLI_INIT:
14574       e->command = "mfcr2 show version";
14575       e->usage =
14576          "Usage: mfcr2 show version\n"
14577          "       Shows the version of the OpenR2 library being used.\n";
14578       return NULL;
14579    case CLI_GENERATE:
14580       return NULL;
14581    }
14582    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14583    return CLI_SUCCESS;
14584 }

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

Definition at line 14181 of file chan_dahdi.c.

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

14182 {
14183    int span;
14184    int x;
14185    int level = 0;
14186    switch (cmd) {
14187    case CLI_INIT:
14188       e->command = "pri set debug {on|off|0|1|2} span";
14189       e->usage =
14190          "Usage: pri set debug {<level>|on|off} span <span>\n"
14191          "       Enables debugging on a given PRI span\n";
14192       return NULL;
14193    case CLI_GENERATE:
14194       return complete_span_4(a->line, a->word, a->pos, a->n);
14195    }
14196    if (a->argc < 6) {
14197       return CLI_SHOWUSAGE;
14198    }
14199 
14200    if (!strcasecmp(a->argv[3], "on")) {
14201       level = 1;
14202    } else if (!strcasecmp(a->argv[3], "off")) {
14203       level = 0;
14204    } else {
14205       level = atoi(a->argv[3]);
14206    }
14207    span = atoi(a->argv[5]);
14208    if ((span < 1) || (span > NUM_SPANS)) {
14209       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14210       return CLI_SUCCESS;
14211    }
14212    if (!pris[span-1].pri.pri) {
14213       ast_cli(a->fd, "No PRI running on span %d\n", span);
14214       return CLI_SUCCESS;
14215    }
14216 
14217    /* Set debug level in libpri */
14218    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14219       if (pris[span - 1].pri.dchans[x]) {
14220          switch (level) {
14221          case 0:
14222             pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14223             break;
14224          case 1:
14225             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14226             break;
14227          default:
14228             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14229             break;
14230          }
14231       }
14232    }
14233    if (level == 0) {
14234       /* Close the debugging file if it's set */
14235       ast_mutex_lock(&pridebugfdlock);
14236       if (0 <= pridebugfd) {
14237          close(pridebugfd);
14238          pridebugfd = -1;
14239          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14240             pridebugfilename);
14241       }
14242       ast_mutex_unlock(&pridebugfdlock);
14243    }
14244    pris[span - 1].pri.debug = (level) ? 1 : 0;
14245    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14246    return CLI_SUCCESS;
14247 }

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

Definition at line 14377 of file chan_dahdi.c.

References CLI_GENERATE, CLI_INIT, ast_cli_entry::command, handle_pri_service_generic(), and ast_cli_entry::usage.

14378 {
14379    switch (cmd) {
14380    case CLI_INIT:
14381       e->command = "pri service disable channel";
14382       e->usage =
14383          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14384          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14385          "  to remove a channel from service, with optional interface id\n"
14386          "  as agreed upon with remote switch operator\n";
14387       return NULL;
14388    case CLI_GENERATE:
14389       return NULL;
14390    }
14391    return handle_pri_service_generic(e, cmd, a, 2);
14392 }

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

Definition at line 14360 of file chan_dahdi.c.

References CLI_GENERATE, CLI_INIT, ast_cli_entry::command, handle_pri_service_generic(), and ast_cli_entry::usage.

14361 {
14362    switch (cmd) {
14363    case CLI_INIT:
14364       e->command = "pri service enable channel";
14365       e->usage =
14366          "Usage: pri service enable channel <channel> [<interface id>]\n"
14367          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14368          "  to restore a channel to service, with optional interface id\n"
14369          "  as agreed upon with remote switch operator\n";
14370       return NULL;
14371    case CLI_GENERATE:
14372       return NULL;
14373    }
14374    return handle_pri_service_generic(e, cmd, a, 0);
14375 }

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

Definition at line 14252 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_FAILURE, CLI_SHOWUSAGE, ast_cli_args::fd, dahdi_pri::pri, pris, and sig_pri_span::trunkgroup.

Referenced by handle_pri_service_disable_channel(), and handle_pri_service_enable_channel().

14253 {
14254    unsigned *why;
14255    int channel;
14256    int trunkgroup;
14257    int x, y, fd = a->fd;
14258    int interfaceid = 0;
14259    char *c;
14260    char db_chan_name[20], db_answer[5];
14261    struct dahdi_pvt *tmp;
14262    struct dahdi_pri *pri;
14263 
14264    if (a->argc < 5 || a->argc > 6)
14265       return CLI_SHOWUSAGE;
14266    if ((c = strchr(a->argv[4], ':'))) {
14267       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14268          return CLI_SHOWUSAGE;
14269       if ((trunkgroup < 1) || (channel < 1))
14270          return CLI_SHOWUSAGE;
14271       pri = NULL;
14272       for (x=0;x<NUM_SPANS;x++) {
14273          if (pris[x].pri.trunkgroup == trunkgroup) {
14274             pri = pris + x;
14275             break;
14276          }
14277       }
14278       if (!pri) {
14279          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14280          return CLI_FAILURE;
14281       }
14282    } else
14283       channel = atoi(a->argv[4]);
14284 
14285    if (a->argc == 6)
14286       interfaceid = atoi(a->argv[5]);
14287 
14288    /* either servicing a D-Channel */
14289    for (x = 0; x < NUM_SPANS; x++) {
14290       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14291          if (pris[x].dchannels[y] == channel) {
14292             pri = pris + x;
14293             if (pri->pri.enable_service_message_support) {
14294                ast_mutex_lock(&pri->pri.lock);
14295                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14296                ast_mutex_unlock(&pri->pri.lock);
14297             } else {
14298                ast_cli(fd,
14299                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14300                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14301             }
14302             return CLI_SUCCESS;
14303          }
14304       }
14305    }
14306 
14307    /* or servicing a B-Channel */
14308    ast_mutex_lock(&iflock);
14309    for (tmp = iflist; tmp; tmp = tmp->next) {
14310       if (tmp->pri && tmp->channel == channel) {
14311          ast_mutex_unlock(&iflock);
14312          ast_mutex_lock(&tmp->pri->lock);
14313          if (!tmp->pri->enable_service_message_support) {
14314             ast_mutex_unlock(&tmp->pri->lock);
14315             ast_cli(fd,
14316                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14317                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14318             return CLI_SUCCESS;
14319          }
14320          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14321          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14322          switch(changestatus) {
14323          case 0: /* enable */
14324             /* Near end wants to be in service now. */
14325             ast_db_del(db_chan_name, SRVST_DBKEY);
14326             *why &= ~SRVST_NEAREND;
14327             if (*why) {
14328                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14329                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14330             } else {
14331                dahdi_pri_update_span_devstate(tmp->pri);
14332             }
14333             break;
14334          /* case 1:  -- loop */
14335          case 2: /* disable */
14336             /* Near end wants to be out-of-service now. */
14337             ast_db_del(db_chan_name, SRVST_DBKEY);
14338             *why |= SRVST_NEAREND;
14339             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14340             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14341             dahdi_pri_update_span_devstate(tmp->pri);
14342             break;
14343          /* case 3:  -- continuity */
14344          /* case 4:  -- shutdown */
14345          default:
14346             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14347             break;
14348          }
14349          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14350          ast_mutex_unlock(&tmp->pri->lock);
14351          return CLI_SUCCESS;
14352       }
14353    }
14354    ast_mutex_unlock(&iflock);
14355 
14356    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14357    return CLI_FAILURE;
14358 }

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

Definition at line 14143 of file chan_dahdi.c.

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

14144 {
14145    int myfd;
14146    switch (cmd) {
14147    case CLI_INIT:
14148       e->command = "pri set debug file";
14149       e->usage = "Usage: pri set debug file [output-file]\n"
14150          "       Sends PRI debug output to the specified output file\n";
14151       return NULL;
14152    case CLI_GENERATE:
14153       return NULL;
14154    }
14155    if (a->argc < 5)
14156       return CLI_SHOWUSAGE;
14157 
14158    if (ast_strlen_zero(a->argv[4]))
14159       return CLI_SHOWUSAGE;
14160 
14161    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14162    if (myfd < 0) {
14163       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14164       return CLI_SUCCESS;
14165    }
14166 
14167    ast_mutex_lock(&pridebugfdlock);
14168 
14169    if (pridebugfd >= 0)
14170       close(pridebugfd);
14171 
14172    pridebugfd = myfd;
14173    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14174    ast_mutex_unlock(&pridebugfdlock);
14175    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14176    return CLI_SUCCESS;
14177 }

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

Definition at line 14397 of file chan_dahdi.c.

References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, ast_cli_args::fd, dahdi_pri::pri, sig_pri_span::pri, sig_pri_chan::pri, pris, sig_pri_cli_show_channels(), sig_pri_cli_show_channels_header(), and ast_cli_entry::usage.

14398 {
14399    int span;
14400 
14401    switch (cmd) {
14402    case CLI_INIT:
14403       e->command = "pri show channels";
14404       e->usage =
14405          "Usage: pri show channels\n"
14406          "       Displays PRI channel information such as the current mapping\n"
14407          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14408          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14409          "       are not associated with any B channel.\n";
14410       return NULL;
14411    case CLI_GENERATE:
14412       return NULL;
14413    }
14414 
14415    if (a->argc != 3)
14416       return CLI_SHOWUSAGE;
14417 
14418    sig_pri_cli_show_channels_header(a->fd);
14419    for (span = 0; span < NUM_SPANS; ++span) {
14420       if (pris[span].pri.pri) {
14421          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14422       }
14423    }
14424    return CLI_SUCCESS;
14425 }

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

Definition at line 14491 of file chan_dahdi.c.

References ast_cli(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, sig_pri_span::dchans, debug, ast_cli_args::fd, sig_pri_span::pri, sig_pri_chan::pri, pris, and ast_cli_entry::usage.

14492 {
14493    int x;
14494    int span;
14495    int count=0;
14496    int debug;
14497 
14498    switch (cmd) {
14499    case CLI_INIT:
14500       e->command = "pri show debug";
14501       e->usage =
14502          "Usage: pri show debug\n"
14503          "  Show the debug state of pri spans\n";
14504       return NULL;
14505    case CLI_GENERATE:
14506       return NULL;
14507    }
14508 
14509    for (span = 0; span < NUM_SPANS; span++) {
14510       if (pris[span].pri.pri) {
14511          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14512             if (pris[span].pri.dchans[x]) {
14513                debug = pri_get_debug(pris[span].pri.dchans[x]);
14514                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" );
14515                count++;
14516             }
14517          }
14518       }
14519 
14520    }
14521    ast_mutex_lock(&pridebugfdlock);
14522    if (pridebugfd >= 0)
14523       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14524    ast_mutex_unlock(&pridebugfdlock);
14525 
14526    if (!count)
14527       ast_cli(a->fd, "No PRI running\n");
14528    return CLI_SUCCESS;
14529 }

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

Definition at line 14457 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_4(), dahdi_pri::dchannels, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, dahdi_pri::pri, sig_pri_span::pri, sig_pri_chan::pri, pris, sig_pri_cli_show_span(), ast_cli_entry::usage, and ast_cli_args::word.

14458 {
14459    int span;
14460 
14461    switch (cmd) {
14462    case CLI_INIT:
14463       e->command = "pri show span";
14464       e->usage =
14465          "Usage: pri show span <span>\n"
14466          "       Displays PRI Information on a given PRI span\n";
14467       return NULL;
14468    case CLI_GENERATE:
14469       return complete_span_4(a->line, a->word, a->pos, a->n);
14470    }
14471 
14472    if (a->argc < 4)
14473       return CLI_SHOWUSAGE;
14474    span = atoi(a->argv[3]);
14475    if ((span < 1) || (span > NUM_SPANS)) {
14476       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14477       return CLI_SUCCESS;
14478    }
14479    if (!pris[span-1].pri.pri) {
14480       ast_cli(a->fd, "No PRI running on span %d\n", span);
14481       return CLI_SUCCESS;
14482    }
14483 
14484    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14485 
14486    return CLI_SUCCESS;
14487 }

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

Definition at line 14429 of file chan_dahdi.c.

References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, ast_cli_args::fd, dahdi_pri::pri, sig_pri_span::pri, sig_pri_chan::pri, pris, sig_pri_cli_show_spans(), and ast_cli_entry::usage.

14430 {
14431    int span;
14432 
14433    switch (cmd) {
14434    case CLI_INIT:
14435       e->command = "pri show spans";
14436       e->usage =
14437          "Usage: pri show spans\n"
14438          "       Displays PRI span information\n";
14439       return NULL;
14440    case CLI_GENERATE:
14441       return NULL;
14442    }
14443 
14444    if (a->argc != 3)
14445       return CLI_SHOWUSAGE;
14446 
14447    for (span = 0; span < NUM_SPANS; span++) {
14448       if (pris[span].pri.pri) {
14449          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14450       }
14451    }
14452    return CLI_SUCCESS;
14453 }

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

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

14534 {
14535    switch (cmd) {
14536    case CLI_INIT:
14537       e->command = "pri show version";
14538       e->usage =
14539          "Usage: pri show version\n"
14540          "Show libpri version information\n";
14541       return NULL;
14542    case CLI_GENERATE:
14543       return NULL;
14544    }
14545 
14546    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14547 
14548    return CLI_SUCCESS;
14549 }

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

Definition at line 16158 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, sig_ss7_linkset::ss7, dahdi_ss7::ss7, and ast_cli_entry::usage.

16159 {
16160    int linkset, cic;
16161    int blocked = -1, i;
16162    switch (cmd) {
16163    case CLI_INIT:
16164       e->command = "ss7 block cic";
16165       e->usage =
16166          "Usage: ss7 block cic <linkset> <CIC>\n"
16167          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16168       return NULL;
16169    case CLI_GENERATE:
16170       return NULL;
16171    }
16172    if (a->argc == 5)
16173       linkset = atoi(a->argv[3]);
16174    else
16175       return CLI_SHOWUSAGE;
16176 
16177    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16178       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16179       return CLI_SUCCESS;
16180    }
16181 
16182    if (!linksets[linkset-1].ss7.ss7) {
16183       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16184       return CLI_SUCCESS;
16185    }
16186 
16187    cic = atoi(a->argv[4]);
16188 
16189    if (cic < 1) {
16190       ast_cli(a->fd, "Invalid CIC specified!\n");
16191       return CLI_SUCCESS;
16192    }
16193 
16194    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16195       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16196          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16197          if (!blocked) {
16198             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16199             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16200             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16201          }
16202       }
16203    }
16204 
16205    if (blocked < 0) {
16206       ast_cli(a->fd, "Invalid CIC specified!\n");
16207       return CLI_SUCCESS;
16208    }
16209 
16210    if (!blocked)
16211       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16212    else
16213       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16214 
16215    /* Break poll on the linkset so it sends our messages */
16216    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16217 
16218    return CLI_SUCCESS;
16219 }

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

Definition at line 16223 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, sig_ss7_linkset::ss7, dahdi_ss7::ss7, and ast_cli_entry::usage.

16224 {
16225    int linkset;
16226    int i;
16227    switch (cmd) {
16228    case CLI_INIT:
16229       e->command = "ss7 block linkset";
16230       e->usage =
16231          "Usage: ss7 block linkset <linkset number>\n"
16232          "       Sends a remote blocking request for all CICs on the given linkset\n";
16233       return NULL;
16234    case CLI_GENERATE:
16235       return NULL;
16236    }
16237    if (a->argc == 4)
16238       linkset = atoi(a->argv[3]);
16239    else
16240       return CLI_SHOWUSAGE;
16241 
16242    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16243       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16244       return CLI_SUCCESS;
16245    }
16246 
16247    if (!linksets[linkset-1].ss7.ss7) {
16248       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16249       return CLI_SUCCESS;
16250    }
16251 
16252    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16253       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16254       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16255       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16256       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16257    }
16258 
16259    /* Break poll on the linkset so it sends our messages */
16260    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16261 
16262    return CLI_SUCCESS;
16263 }

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

Definition at line 16119 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, SIG_SS7_DEBUG, dahdi_ss7::ss7, and ast_cli_entry::usage.

16120 {
16121    int span;
16122    switch (cmd) {
16123    case CLI_INIT:
16124       e->command = "ss7 set debug {on|off} linkset";
16125       e->usage =
16126          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16127          "       Enables debugging on a given SS7 linkset\n";
16128       return NULL;
16129    case CLI_GENERATE:
16130       return NULL;
16131    }
16132    if (a->argc < 6)
16133       return CLI_SHOWUSAGE;
16134    span = atoi(a->argv[5]);
16135    if ((span < 1) || (span > NUM_SPANS)) {
16136       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16137       return CLI_SUCCESS;
16138    }
16139    if (!linksets[span-1].ss7.ss7) {
16140       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16141    } else {
16142       if (!strcasecmp(a->argv[3], "on")) {
16143          linksets[span - 1].ss7.debug = 1;
16144          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16145          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16146       } else {
16147          linksets[span - 1].ss7.debug = 0;
16148          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16149          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16150       }
16151    }
16152 
16153    return CLI_SUCCESS;
16154 }

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

Definition at line 16406 of file chan_dahdi.c.

References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, ast_cli_args::fd, sig_ss7_cli_show_channels(), sig_ss7_cli_show_channels_header(), sig_ss7_linkset::ss7, and ast_cli_entry::usage.

16407 {
16408    int linkset;
16409 
16410    switch (cmd) {
16411    case CLI_INIT:
16412       e->command = "ss7 show channels";
16413       e->usage =
16414          "Usage: ss7 show channels\n"
16415          "       Displays SS7 channel information at a glance.\n";
16416       return NULL;
16417    case CLI_GENERATE:
16418       return NULL;
16419    }
16420 
16421    if (a->argc != 3)
16422       return CLI_SHOWUSAGE;
16423 
16424    sig_ss7_cli_show_channels_header(a->fd);
16425    for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16426       if (linksets[linkset].ss7.ss7) {
16427          sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16428       }
16429    }
16430    return CLI_SUCCESS;
16431 }

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

Definition at line 16371 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, sig_ss7_linkset::LINKSET_STATE_UP, sig_ss7_linkset::ss7, and ast_cli_entry::usage.

16372 {
16373    int linkset;
16374    struct sig_ss7_linkset *ss7;
16375    switch (cmd) {
16376    case CLI_INIT:
16377       e->command = "ss7 show linkset";
16378       e->usage =
16379          "Usage: ss7 show linkset <span>\n"
16380          "       Shows the status of an SS7 linkset.\n";
16381       return NULL;
16382    case CLI_GENERATE:
16383       return NULL;
16384    }
16385 
16386    if (a->argc < 4)
16387       return CLI_SHOWUSAGE;
16388    linkset = atoi(a->argv[3]);
16389    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16390       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16391       return CLI_SUCCESS;
16392    }
16393    ss7 = &linksets[linkset - 1].ss7;
16394    if (!ss7->ss7) {
16395       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16396       return CLI_SUCCESS;
16397    }
16398 
16399    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16400 
16401    return CLI_SUCCESS;
16402 }

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

Definition at line 16267 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, sig_ss7_linkset::ss7, dahdi_ss7::ss7, and ast_cli_entry::usage.

16268 {
16269    int linkset, cic;
16270    int i, blocked = -1;
16271    switch (cmd) {
16272    case CLI_INIT:
16273       e->command = "ss7 unblock cic";
16274       e->usage =
16275          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16276          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16277       return NULL;
16278    case CLI_GENERATE:
16279       return NULL;
16280    }
16281 
16282    if (a->argc == 5)
16283       linkset = atoi(a->argv[3]);
16284    else
16285       return CLI_SHOWUSAGE;
16286 
16287    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16288       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16289       return CLI_SUCCESS;
16290    }
16291 
16292    if (!linksets[linkset-1].ss7.ss7) {
16293       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16294       return CLI_SUCCESS;
16295    }
16296 
16297    cic = atoi(a->argv[4]);
16298 
16299    if (cic < 1) {
16300       ast_cli(a->fd, "Invalid CIC specified!\n");
16301       return CLI_SUCCESS;
16302    }
16303 
16304    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16305       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16306          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16307          if (blocked) {
16308             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16309             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16310             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16311          }
16312       }
16313    }
16314 
16315    if (blocked > 0)
16316       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16317 
16318    /* Break poll on the linkset so it sends our messages */
16319    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16320 
16321    return CLI_SUCCESS;
16322 }

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

Definition at line 16326 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, sig_ss7_linkset::ss7, dahdi_ss7::ss7, and ast_cli_entry::usage.

16327 {
16328    int linkset;
16329    int i;
16330    switch (cmd) {
16331    case CLI_INIT:
16332       e->command = "ss7 unblock linkset";
16333       e->usage =
16334          "Usage: ss7 unblock linkset <linkset number>\n"
16335          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16336       return NULL;
16337    case CLI_GENERATE:
16338       return NULL;
16339    }
16340 
16341    if (a->argc == 4)
16342       linkset = atoi(a->argv[3]);
16343    else
16344       return CLI_SHOWUSAGE;
16345 
16346    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16347       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16348       return CLI_SUCCESS;
16349    }
16350 
16351    if (!linksets[linkset-1].ss7.ss7) {
16352       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16353       return CLI_SUCCESS;
16354    }
16355 
16356    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16357       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16358       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16359       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16360       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16361    }
16362 
16363    /* Break poll on the linkset so it sends our messages */
16364    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16365 
16366    return CLI_SUCCESS;
16367 }

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

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

16436 {
16437    switch (cmd) {
16438    case CLI_INIT:
16439       e->command = "ss7 show version";
16440       e->usage =
16441          "Usage: ss7 show version\n"
16442          "  Show the libss7 version\n";
16443       return NULL;
16444    case CLI_GENERATE:
16445       return NULL;
16446    }
16447 
16448    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16449 
16450    return CLI_SUCCESS;
16451 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

Definition at line 5207 of file chan_dahdi.c.

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

05208 {
05209    int new_msgs;
05210    struct ast_event *event;
05211    char *mailbox, *context;
05212 
05213    mailbox = context = ast_strdupa(p->mailbox);
05214    strsep(&context, "@");
05215    if (ast_strlen_zero(context))
05216       context = "default";
05217 
05218    event = ast_event_get_cached(AST_EVENT_MWI,
05219       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05220       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05221       AST_EVENT_IE_END);
05222 
05223    if (event) {
05224       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05225       ast_event_destroy(event);
05226    } else
05227       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05228 
05229    return new_msgs;
05230 }

static int is_group_or_channel_match ( struct dahdi_pvt p,
int  span,
ast_group_t  groupmatch,
int *  groupmatched,
int  channelmatch,
int *  channelmatched 
) [static]

Definition at line 13051 of file chan_dahdi.c.

References dahdi_pvt::channel, dahdi_pvt::group, dahdi_pvt::pri, and sig_pri_span::span.

Referenced by dahdi_cc_callback(), and dahdi_request().

13052 {
13053 #if defined(HAVE_PRI)
13054    if (0 < span) {
13055       /* The channel must be on the specified PRI span. */
13056       if (!p->pri || p->pri->span != span) {
13057          return 0;
13058       }
13059       if (!groupmatch && channelmatch == -1) {
13060          /* Match any group since it only needs to be on the PRI span. */
13061          *groupmatched = 1;
13062          return 1;
13063       }
13064    }
13065 #endif   /* defined(HAVE_PRI) */
13066    /* check group matching */
13067    if (groupmatch) {
13068       if ((p->group & groupmatch) != groupmatch)
13069          /* Doesn't match the specified group, try the next one */
13070          return 0;
13071       *groupmatched = 1;
13072    }
13073    /* Check to see if we have a channel match */
13074    if (channelmatch != -1) {
13075       if (p->channel != channelmatch)
13076          /* Doesn't match the specified channel, try the next one */
13077          return 0;
13078       *channelmatched = 1;
13079    }
13080 
13081    return 1;
13082 }

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

Definition at line 4689 of file chan_dahdi.c.

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

Referenced by conf_del().

04690 {
04691    /* If they're listening to our channel, they're ours */
04692    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04693       return 1;
04694    /* If they're a talker on our (allocated) conference, they're ours */
04695    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04696       return 1;
04697    return 0;
04698 }

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

Definition at line 4719 of file chan_dahdi.c.

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

Referenced by my_complete_conference_update(), and update_conf().

04720 {
04721    int x;
04722    int useslavenative;
04723    struct dahdi_pvt *slave = NULL;
04724    /* Start out optimistic */
04725    useslavenative = 1;
04726    /* Update conference state in a stateless fashion */
04727    for (x = 0; x < 3; x++) {
04728       /* Any three-way calling makes slave native mode *definitely* out
04729          of the question */
04730       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04731          useslavenative = 0;
04732    }
04733    /* If we don't have any 3-way calls, check to see if we have
04734       precisely one slave */
04735    if (useslavenative) {
04736       for (x = 0; x < MAX_SLAVES; x++) {
04737          if (p->slaves[x]) {
04738             if (slave) {
04739                /* Whoops already have a slave!  No
04740                   slave native and stop right away */
04741                slave = NULL;
04742                useslavenative = 0;
04743                break;
04744             } else {
04745                /* We have one slave so far */
04746                slave = p->slaves[x];
04747             }
04748          }
04749       }
04750    }
04751    /* If no slave, slave native definitely out */
04752    if (!slave)
04753       useslavenative = 0;
04754    else if (slave->law != p->law) {
04755       useslavenative = 0;
04756       slave = NULL;
04757    }
04758    if (out)
04759       *out = slave;
04760    return useslavenative;
04761 }

static int linkset_addsigchan ( int  sigchan  )  [static]

Definition at line 16004 of file chan_dahdi.c.

References ast_log(), cur_adjpointcode, cur_defaultdpc, cur_linkset, cur_networkindicator, cur_pointcode, cur_ss7type, dahdi_close_ss7_fd(), errno, sig_ss7_linkset::fds, sig_ss7_linkset::numsigchans, sig_ss7_add_sigchan(), dahdi_ss7::ss7, and ss7_resolve_linkset().

16005 {
16006    struct dahdi_ss7 *link;
16007    int res;
16008    int curfd;
16009    struct dahdi_params params;
16010    struct dahdi_bufferinfo bi;
16011    struct dahdi_spaninfo si;
16012 
16013    if (sigchan < 0) {
16014       ast_log(LOG_ERROR, "Invalid sigchan!\n");
16015       return -1;
16016    }
16017    if (cur_ss7type < 0) {
16018       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16019       return -1;
16020    }
16021    if (cur_pointcode < 0) {
16022       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16023       return -1;
16024    }
16025    if (cur_adjpointcode < 0) {
16026       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16027       return -1;
16028    }
16029    if (cur_defaultdpc < 0) {
16030       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16031       return -1;
16032    }
16033    if (cur_networkindicator < 0) {
16034       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16035       return -1;
16036    }
16037    link = ss7_resolve_linkset(cur_linkset);
16038    if (!link) {
16039       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16040       return -1;
16041    }
16042    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16043       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16044       return -1;
16045    }
16046 
16047    curfd = link->ss7.numsigchans;
16048 
16049    /* Open signaling channel */
16050    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16051    if (link->ss7.fds[curfd] < 0) {
16052       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16053          strerror(errno));
16054       return -1;
16055    }
16056    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16057       dahdi_close_ss7_fd(link, curfd);
16058       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16059          strerror(errno));
16060       return -1;
16061    }
16062 
16063    /* Get signaling channel parameters */
16064    memset(&params, 0, sizeof(params));
16065    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16066    if (res) {
16067       dahdi_close_ss7_fd(link, curfd);
16068       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16069          strerror(errno));
16070       return -1;
16071    }
16072    if (params.sigtype != DAHDI_SIG_HDLCFCS
16073       && params.sigtype != DAHDI_SIG_HARDHDLC
16074       && params.sigtype != DAHDI_SIG_MTP2) {
16075       dahdi_close_ss7_fd(link, curfd);
16076       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16077       return -1;
16078    }
16079 
16080    /* Set signaling channel buffer policy. */
16081    memset(&bi, 0, sizeof(bi));
16082    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16083    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16084    bi.numbufs = 32;
16085    bi.bufsize = 512;
16086    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16087       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16088          sigchan, strerror(errno));
16089       dahdi_close_ss7_fd(link, curfd);
16090       return -1;
16091    }
16092 
16093    /* Get current signaling channel alarm status. */
16094    memset(&si, 0, sizeof(si));
16095    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16096    if (res) {
16097       dahdi_close_ss7_fd(link, curfd);
16098       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16099          strerror(errno));
16100    }
16101 
16102    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16103       (params.sigtype == DAHDI_SIG_MTP2)
16104          ? SS7_TRANSPORT_DAHDIMTP2
16105          : SS7_TRANSPORT_DAHDIDCHAN,
16106       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16107    if (res) {
16108       dahdi_close_ss7_fd(link, curfd);
16109       return -1;
16110    }
16111 
16112    ++link->ss7.numsigchans;
16113 
16114    return 0;
16115 }

static int load_module ( void   )  [static]

Definition at line 18430 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_cc_agent_register(), ast_cc_monitor_register(), ast_channel_register(), ast_cli_register_multiple(), ast_cond_init, ast_data_register_multiple, ast_log(), ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, ast_register_application_xml, dahdi_accept_r2_call_exec(), dahdi_cli, dahdi_data_providers, dahdi_mfcr2_cli, dahdi_pri_cc_agent_callbacks, dahdi_pri_cc_monitor_callbacks, dahdi_pri_cc_type, dahdi_pri_cli, dahdi_pri_error(), dahdi_pri_message(), dahdi_send_callrerouting_facility_exec(), dahdi_send_keypad_facility_exec(), dahdi_ss7_cli, dahdi_ss7_error(), dahdi_ss7_message(), dahdi_tech, HAVE_PRI_CCSS, round_robin, setup_dahdi(), sig_pri_init_pri(), sig_pri_load(), sig_ss7_init_linkset(), and ss_thread_complete.

18431 {
18432    int res;
18433 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18434    int y;
18435 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18436 
18437 #ifdef HAVE_PRI
18438    memset(pris, 0, sizeof(pris));
18439    for (y = 0; y < NUM_SPANS; y++) {
18440       sig_pri_init_pri(&pris[y].pri);
18441    }
18442    pri_set_error(dahdi_pri_error);
18443    pri_set_message(dahdi_pri_message);
18444    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18445 #ifdef HAVE_PRI_PROG_W_CAUSE
18446    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18447 #endif
18448 #if defined(HAVE_PRI_CCSS)
18449    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18450       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18451       __unload_module();
18452       return AST_MODULE_LOAD_FAILURE;
18453    }
18454 #endif   /* defined(HAVE_PRI_CCSS) */
18455    if (sig_pri_load(
18456 #if defined(HAVE_PRI_CCSS)
18457       dahdi_pri_cc_type
18458 #else
18459       NULL
18460 #endif   /* defined(HAVE_PRI_CCSS) */
18461       )) {
18462       __unload_module();
18463       return AST_MODULE_LOAD_FAILURE;
18464    }
18465 #endif
18466 #if defined(HAVE_SS7)
18467    memset(linksets, 0, sizeof(linksets));
18468    for (y = 0; y < NUM_SPANS; y++) {
18469       sig_ss7_init_linkset(&linksets[y].ss7);
18470    }
18471    ss7_set_error(dahdi_ss7_error);
18472    ss7_set_message(dahdi_ss7_message);
18473 #endif   /* defined(HAVE_SS7) */
18474    res = setup_dahdi(0);
18475    /* Make sure we can register our DAHDI channel type */
18476    if (res)
18477       return AST_MODULE_LOAD_DECLINE;
18478    if (ast_channel_register(&dahdi_tech)) {
18479       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18480       __unload_module();
18481       return AST_MODULE_LOAD_FAILURE;
18482    }
18483 #ifdef HAVE_PRI
18484    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18485 #endif
18486 #if defined(HAVE_SS7)
18487    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18488 #endif   /* defined(HAVE_SS7) */
18489 #ifdef HAVE_OPENR2
18490    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18491    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18492 #endif
18493 
18494    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18495    /* register all the data providers */
18496    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18497    memset(round_robin, 0, sizeof(round_robin));
18498    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18499    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18500    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18501    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18502    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18503    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18504    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18505 
18506    ast_cond_init(&ss_thread_complete, NULL);
18507 
18508    return res;
18509 }

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

Definition at line 13874 of file chan_dahdi.c.

References ast_log(), LOG_DEBUG, and SUB_REAL.

13875 {
13876    struct dahdi_mfcr2 *mfcr2 = data;
13877    /* we should be using pthread_key_create
13878       and allocate pollers dynamically.
13879       I think do_monitor() could be leaking, since it
13880       could be cancelled at any time and is not
13881       using thread keys, why?, */
13882    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13883    int res = 0;
13884    int i = 0;
13885    int oldstate = 0;
13886    int quit_loop = 0;
13887    int maxsleep = 20;
13888    int was_idle = 0;
13889    int pollsize = 0;
13890    /* now that we're ready to get calls, unblock our side and
13891       get current line state */
13892    for (i = 0; i < mfcr2->numchans; i++) {
13893       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
13894       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
13895    }
13896    while (1) {
13897       /* we trust here that the mfcr2 channel list will not ever change once
13898          the module is loaded */
13899       pollsize = 0;
13900       for (i = 0; i < mfcr2->numchans; i++) {
13901          pollers[i].revents = 0;
13902          pollers[i].events = 0;
13903          if (mfcr2->pvts[i]->owner) {
13904             continue;
13905          }
13906          if (!mfcr2->pvts[i]->r2chan) {
13907             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
13908             quit_loop = 1;
13909             break;
13910          }
13911          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
13912          pollers[i].events = POLLIN | POLLPRI;
13913          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
13914          pollsize++;
13915       }
13916       if (quit_loop) {
13917          break;
13918       }
13919       if (pollsize == 0) {
13920          if (!was_idle) {
13921             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
13922             was_idle = 1;
13923          }
13924          poll(NULL, 0, maxsleep);
13925          continue;
13926       }
13927       was_idle = 0;
13928       /* probably poll() is a valid cancel point, lets just be on the safe side
13929          by calling pthread_testcancel */
13930       pthread_testcancel();
13931       res = poll(pollers, mfcr2->numchans, maxsleep);
13932       pthread_testcancel();
13933       if ((res < 0) && (errno != EINTR)) {
13934          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
13935          break;
13936       }
13937       /* do we want to allow to cancel while processing events? */
13938       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
13939       for (i = 0; i < mfcr2->numchans; i++) {
13940          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
13941             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
13942          }
13943       }
13944       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
13945    }
13946    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
13947    return 0;
13948 }

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

Definition at line 12166 of file chan_dahdi.c.

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

Referenced by build_channels().

12167 {
12168    /* Make a dahdi_pvt structure for this interface */
12169    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12170    char fn[80];
12171    struct dahdi_bufferinfo bi;
12172 
12173    int res;
12174 #if defined(HAVE_PRI)
12175    int span = 0;
12176 #endif   /* defined(HAVE_PRI) */
12177    int here = 0;/*!< TRUE if the channel interface already exists. */
12178    int x;
12179    struct analog_pvt *analog_p = NULL;
12180    struct dahdi_params p;
12181 #if defined(HAVE_PRI)
12182    struct dahdi_spaninfo si;
12183    struct sig_pri_chan *pri_chan = NULL;
12184 #endif   /* defined(HAVE_PRI) */
12185 #if defined(HAVE_SS7)
12186    struct sig_ss7_chan *ss7_chan = NULL;
12187 #endif   /* defined(HAVE_SS7) */
12188 
12189    /* Search channel interface list to see if it already exists. */
12190    for (tmp = iflist; tmp; tmp = tmp->next) {
12191       if (!tmp->destroy) {
12192          if (tmp->channel == channel) {
12193             /* The channel interface already exists. */
12194             here = 1;
12195             break;
12196          }
12197          if (tmp->channel > channel) {
12198             /* No way it can be in the sorted list. */
12199             tmp = NULL;
12200             break;
12201          }
12202       }
12203    }
12204 
12205    if (!here && reloading != 1) {
12206       tmp = ast_calloc(1, sizeof(*tmp));
12207       if (!tmp) {
12208          return NULL;
12209       }
12210       tmp->cc_params = ast_cc_config_params_init();
12211       if (!tmp->cc_params) {
12212          ast_free(tmp);
12213          return NULL;
12214       }
12215       ast_mutex_init(&tmp->lock);
12216       ifcount++;
12217       for (x = 0; x < 3; x++)
12218          tmp->subs[x].dfd = -1;
12219       tmp->channel = channel;
12220       tmp->priindication_oob = conf->chan.priindication_oob;
12221    }
12222 
12223    if (tmp) {
12224       int chan_sig = conf->chan.sig;
12225 
12226       /* If there are variables in tmp before it is updated to match the new config, clear them */
12227       if (reloading && tmp->vars) {
12228          ast_variables_destroy(tmp->vars);
12229          tmp->vars = NULL;
12230       }
12231 
12232 
12233       if (!here) {
12234          /* Can only get here if this is a new channel interface being created. */
12235          if ((channel != CHAN_PSEUDO)) {
12236             int count = 0;
12237 
12238             snprintf(fn, sizeof(fn), "%d", channel);
12239             /* Open non-blocking */
12240             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12241             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 */
12242                usleep(1);
12243                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12244                count++;
12245             }
12246             /* Allocate a DAHDI structure */
12247             if (tmp->subs[SUB_REAL].dfd < 0) {
12248                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);
12249                destroy_dahdi_pvt(tmp);
12250                return NULL;
12251             }
12252             memset(&p, 0, sizeof(p));
12253             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12254             if (res < 0) {
12255                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12256                destroy_dahdi_pvt(tmp);
12257                return NULL;
12258             }
12259             if (conf->is_sig_auto)
12260                chan_sig = sigtype_to_signalling(p.sigtype);
12261             if (p.sigtype != (chan_sig & 0x3ffff)) {
12262                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));
12263                destroy_dahdi_pvt(tmp);
12264                return NULL;
12265             }
12266             tmp->law_default = p.curlaw;
12267             tmp->law = p.curlaw;
12268             tmp->span = p.spanno;
12269 #if defined(HAVE_PRI)
12270             span = p.spanno - 1;
12271 #endif   /* defined(HAVE_PRI) */
12272          } else {
12273             chan_sig = 0;
12274          }
12275          tmp->sig = chan_sig;
12276          tmp->outsigmod = conf->chan.outsigmod;
12277 
12278          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12279             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12280             if (!analog_p) {
12281                destroy_dahdi_pvt(tmp);
12282                return NULL;
12283             }
12284             tmp->sig_pvt = analog_p;
12285          }
12286 #if defined(HAVE_SS7)
12287          if (chan_sig == SIG_SS7) {
12288             struct dahdi_ss7 *ss7;
12289             int clear = 0;
12290 
12291             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12292                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12293                destroy_dahdi_pvt(tmp);
12294                return NULL;
12295             }
12296 
12297             ss7 = ss7_resolve_linkset(cur_linkset);
12298             if (!ss7) {
12299                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12300                destroy_dahdi_pvt(tmp);
12301                return NULL;
12302             }
12303             ss7->ss7.span = cur_linkset;
12304             if (cur_cicbeginswith < 0) {
12305                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12306                destroy_dahdi_pvt(tmp);
12307                return NULL;
12308             }
12309             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12310             if (!ss7_chan) {
12311                destroy_dahdi_pvt(tmp);
12312                return NULL;
12313             }
12314             tmp->sig_pvt = ss7_chan;
12315             tmp->ss7 = &ss7->ss7;
12316 
12317             ss7_chan->channel = tmp->channel;
12318             ss7_chan->cic = cur_cicbeginswith++;
12319 
12320             /* DB: Add CIC's DPC information */
12321             ss7_chan->dpc = cur_defaultdpc;
12322 
12323             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12324 
12325             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12326             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12327             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12328             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12329 
12330             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12331             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12332          }
12333 #endif   /* defined(HAVE_SS7) */
12334 #ifdef HAVE_OPENR2
12335          if (chan_sig == SIG_MFCR2) {
12336             struct dahdi_mfcr2 *r2_link;
12337             r2_link = dahdi_r2_get_link();
12338             if (!r2_link) {
12339                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12340                destroy_dahdi_pvt(tmp);
12341                return NULL;
12342             }
12343             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12344                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12345                destroy_dahdi_pvt(tmp);
12346                return NULL;
12347             }
12348             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12349                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12350                destroy_dahdi_pvt(tmp);
12351                return NULL;
12352             }
12353             r2_link->pvts[r2_link->numchans++] = tmp;
12354             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12355                                         tmp->subs[SUB_REAL].dfd,
12356                                         NULL, NULL);
12357             if (!tmp->r2chan) {
12358                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12359                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12360                destroy_dahdi_pvt(tmp);
12361                return NULL;
12362             }
12363             tmp->mfcr2 = r2_link;
12364             if (conf->mfcr2.call_files) {
12365                openr2_chan_enable_call_files(tmp->r2chan);
12366             }
12367             openr2_chan_set_client_data(tmp->r2chan, tmp);
12368             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12369             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12370             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12371             tmp->mfcr2_category = conf->mfcr2.category;
12372             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12373             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12374             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12375             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12376             tmp->mfcr2call = 0;
12377             tmp->mfcr2_dnis_index = 0;
12378             tmp->mfcr2_ani_index = 0;
12379             r2_link->monitored_count++;
12380          }
12381 #endif
12382 #ifdef HAVE_PRI
12383          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12384             int offset;
12385             int matchesdchan;
12386             int x,y;
12387             int myswitchtype = 0;
12388 
12389             offset = 0;
12390             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12391                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12392                destroy_dahdi_pvt(tmp);
12393                return NULL;
12394             }
12395             if (span >= NUM_SPANS) {
12396                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12397                destroy_dahdi_pvt(tmp);
12398                return NULL;
12399             } else {
12400                si.spanno = 0;
12401                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12402                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12403                   destroy_dahdi_pvt(tmp);
12404                   return NULL;
12405                }
12406                /* Store the logical span first based upon the real span */
12407                tmp->logicalspan = pris[span].prilogicalspan;
12408                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12409                if (span < 0) {
12410                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12411                   destroy_dahdi_pvt(tmp);
12412                   return NULL;
12413                }
12414                myswitchtype = conf->pri.pri.switchtype;
12415                /* Make sure this isn't a d-channel */
12416                matchesdchan=0;
12417                for (x = 0; x < NUM_SPANS; x++) {
12418                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12419                      if (pris[x].dchannels[y] == tmp->channel) {
12420                         matchesdchan = 1;
12421                         break;
12422                      }
12423                   }
12424                }
12425                if (!matchesdchan) {
12426                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12427                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12428                      destroy_dahdi_pvt(tmp);
12429                      return NULL;
12430                   }
12431                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12432                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12433                      destroy_dahdi_pvt(tmp);
12434                      return NULL;
12435                   }
12436                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12437                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, pris[span].pri.dialplan == -1 ? "Dynamically set dialplan in ISDN" : pri_plan2str(pris[span].pri.dialplan));
12438                      destroy_dahdi_pvt(tmp);
12439                      return NULL;
12440                   }
12441                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12442                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12443                      destroy_dahdi_pvt(tmp);
12444                      return NULL;
12445                   }
12446                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12447                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12448                      destroy_dahdi_pvt(tmp);
12449                      return NULL;
12450                   }
12451                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12452                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12453                      destroy_dahdi_pvt(tmp);
12454                      return NULL;
12455                   }
12456                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12457                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12458                      destroy_dahdi_pvt(tmp);
12459                      return NULL;
12460                   }
12461                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12462                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12463                         pris[span].pri.trunkgroup);
12464                      destroy_dahdi_pvt(tmp);
12465                      return NULL;
12466                   }
12467 
12468                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12469                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12470                   if (!pri_chan) {
12471                      destroy_dahdi_pvt(tmp);
12472                      return NULL;
12473                   }
12474                   tmp->sig_pvt = pri_chan;
12475                   tmp->pri = &pris[span].pri;
12476 
12477                   tmp->priexclusive = conf->chan.priexclusive;
12478 
12479                   if (!tmp->pri->cc_params) {
12480                      tmp->pri->cc_params = ast_cc_config_params_init();
12481                      if (!tmp->pri->cc_params) {
12482                         destroy_dahdi_pvt(tmp);
12483                         return NULL;
12484                      }
12485                   }
12486                   ast_cc_copy_config_params(tmp->pri->cc_params,
12487                      conf->chan.cc_params);
12488 
12489                   pris[span].pri.sig = chan_sig;
12490                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12491                   pris[span].pri.switchtype = myswitchtype;
12492                   pris[span].pri.nsf = conf->pri.pri.nsf;
12493                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12494                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12495                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12496                   pris[span].pri.minunused = conf->pri.pri.minunused;
12497                   pris[span].pri.minidle = conf->pri.pri.minidle;
12498                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12499                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12500                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12501 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12502                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12503 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12504 #ifdef HAVE_PRI_INBANDDISCONNECT
12505                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12506 #endif
12507 #if defined(HAVE_PRI_CALL_HOLD)
12508                   pris[span].pri.hold_disconnect_transfer =
12509                      conf->pri.pri.hold_disconnect_transfer;
12510 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12511 #if defined(HAVE_PRI_CCSS)
12512                   pris[span].pri.cc_ptmp_recall_mode =
12513                      conf->pri.pri.cc_ptmp_recall_mode;
12514                   pris[span].pri.cc_qsig_signaling_link_req =
12515                      conf->pri.pri.cc_qsig_signaling_link_req;
12516                   pris[span].pri.cc_qsig_signaling_link_rsp =
12517                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12518 #endif   /* defined(HAVE_PRI_CCSS) */
12519 #if defined(HAVE_PRI_CALL_WAITING)
12520                   pris[span].pri.max_call_waiting_calls =
12521                      conf->pri.pri.max_call_waiting_calls;
12522                   pris[span].pri.allow_call_waiting_calls =
12523                      conf->pri.pri.allow_call_waiting_calls;
12524 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12525                   pris[span].pri.transfer = conf->chan.transfer;
12526                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12527 #if defined(HAVE_PRI_L2_PERSISTENCE)
12528                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12529 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12530 #if defined(HAVE_PRI_AOC_EVENTS)
12531                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12532                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12533 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12534                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12535                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12536                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12537 #if defined(HAVE_PRI_MWI)
12538                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12539                      conf->pri.pri.mwi_mailboxes,
12540                      sizeof(pris[span].pri.mwi_mailboxes));
12541 #endif   /* defined(HAVE_PRI_MWI) */
12542                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12543                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12544                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12545                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12546                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12547                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12548                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12549                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12550 
12551                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12552                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12553                   }
12554 
12555 #if defined(HAVE_PRI_CALL_WAITING)
12556                   /* Channel initial config parameters. */
12557                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12558                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12559                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12560                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12561                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12562                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12563                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12564                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12565                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12566                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12567 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12568                } else {
12569                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12570                   destroy_dahdi_pvt(tmp);
12571                   return NULL;
12572                }
12573             }
12574          }
12575 #endif
12576       } else {
12577          /* already exists in interface list */
12578          ast_log(LOG_WARNING, "Attempt to configure channel %d with signaling %s ignored because it is already configured to be %s.\n", tmp->channel, dahdi_sig2str(chan_sig), dahdi_sig2str(tmp->sig));
12579          chan_sig = tmp->sig;
12580          if (tmp->subs[SUB_REAL].dfd > -1) {
12581             memset(&p, 0, sizeof(p));
12582             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12583          }
12584       }
12585       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12586       switch (chan_sig) {
12587       case SIG_FXSKS:
12588       case SIG_FXSLS:
12589       case SIG_EM:
12590       case SIG_EM_E1:
12591       case SIG_EMWINK:
12592       case SIG_FEATD:
12593       case SIG_FEATDMF:
12594       case SIG_FEATDMF_TA:
12595       case SIG_FEATB:
12596       case SIG_E911:
12597       case SIG_SF:
12598       case SIG_SFWINK:
12599       case SIG_FGC_CAMA:
12600       case SIG_FGC_CAMAMF:
12601       case SIG_SF_FEATD:
12602       case SIG_SF_FEATDMF:
12603       case SIG_SF_FEATB:
12604          p.starttime = 250;
12605          break;
12606       }
12607 
12608       if (tmp->radio) {
12609          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12610          p.channo = channel;
12611          p.rxwinktime = 1;
12612          p.rxflashtime = 1;
12613          p.starttime = 1;
12614          p.debouncetime = 5;
12615       } else {
12616          p.channo = channel;
12617          /* Override timing settings based on config file */
12618          if (conf->timing.prewinktime >= 0)
12619             p.prewinktime = conf->timing.prewinktime;
12620          if (conf->timing.preflashtime >= 0)
12621             p.preflashtime = conf->timing.preflashtime;
12622          if (conf->timing.winktime >= 0)
12623             p.winktime = conf->timing.winktime;
12624          if (conf->timing.flashtime >= 0)
12625             p.flashtime = conf->timing.flashtime;
12626          if (conf->timing.starttime >= 0)
12627             p.starttime = conf->timing.starttime;
12628          if (conf->timing.rxwinktime >= 0)
12629             p.rxwinktime = conf->timing.rxwinktime;
12630          if (conf->timing.rxflashtime >= 0)
12631             p.rxflashtime = conf->timing.rxflashtime;
12632          if (conf->timing.debouncetime >= 0)
12633             p.debouncetime = conf->timing.debouncetime;
12634       }
12635 
12636       /* don't set parms on a pseudo-channel */
12637       if (tmp->subs[SUB_REAL].dfd >= 0)
12638       {
12639          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12640          if (res < 0) {
12641             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12642             destroy_dahdi_pvt(tmp);
12643             return NULL;
12644          }
12645       }
12646 #if 1
12647       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12648          memset(&bi, 0, sizeof(bi));
12649          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12650          if (!res) {
12651             bi.txbufpolicy = conf->chan.buf_policy;
12652             bi.rxbufpolicy = conf->chan.buf_policy;
12653             bi.numbufs = conf->chan.buf_no;
12654             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12655             if (res < 0) {
12656                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12657             }
12658          } else {
12659             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12660          }
12661          tmp->buf_policy = conf->chan.buf_policy;
12662          tmp->buf_no = conf->chan.buf_no;
12663          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12664          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12665          tmp->faxbuf_no = conf->chan.faxbuf_no;
12666          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12667           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12668           * The reason the ioctl call above failed should to be determined before worrying about the
12669           * faxbuffer-related ioctl calls */
12670          tmp->bufsize = bi.bufsize;
12671       }
12672 #endif
12673       tmp->immediate = conf->chan.immediate;
12674       tmp->transfertobusy = conf->chan.transfertobusy;
12675       if (chan_sig & __DAHDI_SIG_FXS) {
12676          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12677          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12678          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12679       }
12680       tmp->ringt_base = ringt_base;
12681       tmp->firstradio = 0;
12682       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12683          tmp->permcallwaiting = conf->chan.callwaiting;
12684       else
12685          tmp->permcallwaiting = 0;
12686       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12687       tmp->destroy = 0;
12688       tmp->drings = conf->chan.drings;
12689 
12690       /* 10 is a nice default. */
12691       if (tmp->drings.ringnum[0].range == 0)
12692          tmp->drings.ringnum[0].range = 10;
12693       if (tmp->drings.ringnum[1].range == 0)
12694          tmp->drings.ringnum[1].range = 10;
12695       if (tmp->drings.ringnum[2].range == 0)
12696          tmp->drings.ringnum[2].range = 10;
12697 
12698       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12699       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12700       tmp->threewaycalling = conf->chan.threewaycalling;
12701       tmp->adsi = conf->chan.adsi;
12702       tmp->use_smdi = conf->chan.use_smdi;
12703       tmp->permhidecallerid = conf->chan.hidecallerid;
12704       tmp->hidecalleridname = conf->chan.hidecalleridname;
12705       tmp->callreturn = conf->chan.callreturn;
12706       tmp->echocancel = conf->chan.echocancel;
12707       tmp->echotraining = conf->chan.echotraining;
12708       tmp->pulse = conf->chan.pulse;
12709       if (tmp->echocancel.head.tap_length) {
12710          tmp->echocanbridged = conf->chan.echocanbridged;
12711       } else {
12712          if (conf->chan.echocanbridged)
12713             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12714          tmp->echocanbridged = 0;
12715       }
12716       tmp->busydetect = conf->chan.busydetect;
12717       tmp->busycount = conf->chan.busycount;
12718       tmp->busycompare = conf->chan.busycompare;
12719       tmp->busytonelength = conf->chan.busytonelength;
12720       tmp->busyquietlength = conf->chan.busyquietlength;
12721       tmp->busyfuzziness = conf->chan.busyfuzziness;
12722       tmp->silencethreshold = conf->chan.silencethreshold;
12723       tmp->callprogress = conf->chan.callprogress;
12724       tmp->waitfordialtone = conf->chan.waitfordialtone;
12725       tmp->cancallforward = conf->chan.cancallforward;
12726       tmp->dtmfrelax = conf->chan.dtmfrelax;
12727       tmp->callwaiting = tmp->permcallwaiting;
12728       tmp->hidecallerid = tmp->permhidecallerid;
12729       tmp->channel = channel;
12730       tmp->stripmsd = conf->chan.stripmsd;
12731       tmp->use_callerid = conf->chan.use_callerid;
12732       tmp->cid_signalling = conf->chan.cid_signalling;
12733       tmp->cid_start = conf->chan.cid_start;
12734       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12735       tmp->restrictcid = conf->chan.restrictcid;
12736       tmp->use_callingpres = conf->chan.use_callingpres;
12737       if (tmp->usedistinctiveringdetection) {
12738          if (!tmp->use_callerid) {
12739             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12740             tmp->use_callerid = 1;
12741          }
12742       }
12743 
12744       if (tmp->cid_signalling == CID_SIG_SMDI) {
12745          if (!tmp->use_smdi) {
12746             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12747             tmp->use_smdi = 1;
12748          }
12749       }
12750       if (tmp->use_smdi) {
12751          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12752          if (!(tmp->smdi_iface)) {
12753             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12754             tmp->use_smdi = 0;
12755          }
12756       }
12757 
12758       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12759       tmp->amaflags = conf->chan.amaflags;
12760       if (!here) {
12761          tmp->confno = -1;
12762          tmp->propconfno = -1;
12763       }
12764       tmp->canpark = conf->chan.canpark;
12765       tmp->transfer = conf->chan.transfer;
12766       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12767       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12768       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12769       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12770       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12771       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12772       tmp->cid_ton = 0;
12773       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12774          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12775          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12776       } else {
12777          tmp->cid_num[0] = '\0';
12778          tmp->cid_name[0] = '\0';
12779       }
12780 #if defined(HAVE_PRI)
12781       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12782          tmp->cid_tag[0] = '\0';
12783       } else
12784 #endif   /* defined(HAVE_PRI) */
12785       {
12786          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12787       }
12788       tmp->cid_subaddr[0] = '\0';
12789       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12790       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12791          char *mailbox, *context;
12792          mailbox = context = ast_strdupa(tmp->mailbox);
12793          strsep(&context, "@");
12794          if (ast_strlen_zero(context))
12795             context = "default";
12796          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12797             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12798             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12799             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12800             AST_EVENT_IE_END);
12801       }
12802 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12803       tmp->mwisend_setting = conf->chan.mwisend_setting;
12804       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12805       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12806 #endif
12807 
12808       tmp->group = conf->chan.group;
12809       tmp->callgroup = conf->chan.callgroup;
12810       tmp->pickupgroup= conf->chan.pickupgroup;
12811       if (conf->chan.vars) {
12812          struct ast_variable *v, *tmpvar;
12813                    for (v = conf->chan.vars ; v ; v = v->next) {
12814                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12815                                   tmpvar->next = tmp->vars;
12816                                    tmp->vars = tmpvar;
12817                            }
12818                   }
12819       }
12820       tmp->cid_rxgain = conf->chan.cid_rxgain;
12821       tmp->rxgain = conf->chan.rxgain;
12822       tmp->txgain = conf->chan.txgain;
12823       tmp->txdrc = conf->chan.txdrc;
12824       tmp->rxdrc = conf->chan.rxdrc;
12825       tmp->tonezone = conf->chan.tonezone;
12826       if (tmp->subs[SUB_REAL].dfd > -1) {
12827          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12828          if (tmp->dsp)
12829             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12830          update_conf(tmp);
12831          if (!here) {
12832             switch (chan_sig) {
12833             case SIG_PRI_LIB_HANDLE_CASES:
12834             case SIG_SS7:
12835             case SIG_MFCR2:
12836                break;
12837             default:
12838                /* Hang it up to be sure it's good */
12839                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12840                break;
12841             }
12842          }
12843          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12844          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12845             /* the dchannel is down so put the channel in alarm */
12846             switch (tmp->sig) {
12847 #ifdef HAVE_PRI
12848             case SIG_PRI_LIB_HANDLE_CASES:
12849                sig_pri_set_alarm(tmp->sig_pvt, 1);
12850                break;
12851 #endif
12852 #if defined(HAVE_SS7)
12853             case SIG_SS7:
12854                sig_ss7_set_alarm(tmp->sig_pvt, 1);
12855                break;
12856 #endif   /* defined(HAVE_SS7) */
12857             default:
12858                /* The only sig submodule left should be sig_analog. */
12859                analog_p = tmp->sig_pvt;
12860                if (analog_p) {
12861                   analog_p->inalarm = 1;
12862                }
12863                tmp->inalarm = 1;
12864                break;
12865             }
12866             handle_alarms(tmp, res);
12867          }
12868       }
12869 
12870       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12871       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12872       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12873       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12874       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12875 
12876       if (!here) {
12877          tmp->locallyblocked = 0;
12878          tmp->remotelyblocked = 0;
12879          switch (tmp->sig) {
12880 #if defined(HAVE_PRI)
12881          case SIG_PRI_LIB_HANDLE_CASES:
12882             tmp->inservice = 1;/* Inservice until actually implemented. */
12883 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12884             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
12885             if (chan_sig == SIG_PRI) {
12886                char db_chan_name[20];
12887                char db_answer[5];
12888 
12889                /*
12890                 * Initialize the active out-of-service status
12891                 * and delete any record if the feature is not enabled.
12892                 */
12893                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
12894                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
12895                   unsigned *why;
12896 
12897                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
12898                   if (tmp->pri->enable_service_message_support) {
12899                      char state;
12900 
12901                      sscanf(db_answer, "%1c:%30u", &state, why);
12902 
12903                      /* Ensure that only the implemented bits could be set.*/
12904                      *why &= (SRVST_NEAREND | SRVST_FAREND);
12905                   }
12906                   if (!*why) {
12907                      ast_db_del(db_chan_name, SRVST_DBKEY);
12908                   }
12909                }
12910             }
12911 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12912             break;
12913 #endif   /* defined(HAVE_PRI) */
12914 #if defined(HAVE_SS7)
12915          case SIG_SS7:
12916             tmp->inservice = 0;
12917             break;
12918 #endif   /* defined(HAVE_SS7) */
12919          default:
12920              /* We default to in service on protocols that don't have a reset */
12921             tmp->inservice = 1;
12922             break;
12923          }
12924       }
12925 
12926       switch (tmp->sig) {
12927 #if defined(HAVE_PRI)
12928       case SIG_PRI_LIB_HANDLE_CASES:
12929          if (pri_chan) {
12930             pri_chan->channel = tmp->channel;
12931             pri_chan->hidecallerid = tmp->hidecallerid;
12932             pri_chan->hidecalleridname = tmp->hidecalleridname;
12933             pri_chan->immediate = tmp->immediate;
12934             pri_chan->inalarm = tmp->inalarm;
12935             pri_chan->priexclusive = tmp->priexclusive;
12936             pri_chan->priindication_oob = tmp->priindication_oob;
12937             pri_chan->use_callerid = tmp->use_callerid;
12938             pri_chan->use_callingpres = tmp->use_callingpres;
12939             ast_copy_string(pri_chan->context, tmp->context,
12940                sizeof(pri_chan->context));
12941             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
12942                sizeof(pri_chan->mohinterpret));
12943             pri_chan->stripmsd = tmp->stripmsd;
12944          }
12945          break;
12946 #endif   /* defined(HAVE_PRI) */
12947 #if defined(HAVE_SS7)
12948       case SIG_SS7:
12949          if (ss7_chan) {
12950             ss7_chan->inalarm = tmp->inalarm;
12951 
12952             ss7_chan->stripmsd = tmp->stripmsd;
12953             ss7_chan->hidecallerid = tmp->hidecallerid;
12954             ss7_chan->use_callerid = tmp->use_callerid;
12955             ss7_chan->use_callingpres = tmp->use_callingpres;
12956             ss7_chan->immediate = tmp->immediate;
12957             ss7_chan->locallyblocked = tmp->locallyblocked;
12958             ss7_chan->remotelyblocked = tmp->remotelyblocked;
12959             ast_copy_string(ss7_chan->context, tmp->context,
12960                sizeof(ss7_chan->context));
12961             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
12962                sizeof(ss7_chan->mohinterpret));
12963          }
12964          break;
12965 #endif   /* defined(HAVE_SS7) */
12966       default:
12967          /* The only sig submodule left should be sig_analog. */
12968          analog_p = tmp->sig_pvt;
12969          if (analog_p) {
12970             analog_p->channel = tmp->channel;
12971             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12972             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12973             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12974             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
12975             analog_p->callreturn = conf->chan.callreturn;
12976             analog_p->cancallforward = conf->chan.cancallforward;
12977             analog_p->canpark = conf->chan.canpark;
12978             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
12979             analog_p->immediate = conf->chan.immediate;
12980             analog_p->permhidecallerid = conf->chan.permhidecallerid;
12981             analog_p->pulse = conf->chan.pulse;
12982             analog_p->threewaycalling = conf->chan.threewaycalling;
12983             analog_p->transfer = conf->chan.transfer;
12984             analog_p->transfertobusy = conf->chan.transfertobusy;
12985             analog_p->use_callerid = tmp->use_callerid;
12986             analog_p->use_smdi = tmp->use_smdi;
12987             analog_p->smdi_iface = tmp->smdi_iface;
12988             analog_p->outsigmod = ANALOG_SIG_NONE;
12989             analog_p->echotraining = conf->chan.echotraining;
12990             analog_p->cid_signalling = conf->chan.cid_signalling;
12991             analog_p->stripmsd = conf->chan.stripmsd;
12992             switch (conf->chan.cid_start) {
12993             case CID_START_POLARITY:
12994                analog_p->cid_start = ANALOG_CID_START_POLARITY;
12995                break;
12996             case CID_START_POLARITY_IN:
12997                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
12998                break;
12999             case CID_START_DTMF_NOALERT:
13000                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13001                break;
13002             default:
13003                analog_p->cid_start = ANALOG_CID_START_RING;
13004                break;
13005             }
13006             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13007             analog_p->ringt = conf->chan.ringt;
13008             analog_p->ringt_base = ringt_base;
13009             analog_p->chan_tech = &dahdi_tech;
13010             analog_p->onhooktime = time(NULL);
13011             if (chan_sig & __DAHDI_SIG_FXO) {
13012                memset(&p, 0, sizeof(p));
13013                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13014                if (!res) {
13015                   analog_p->fxsoffhookstate = p.rxisoffhook;
13016                }
13017 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13018                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13019 #endif
13020             }
13021             analog_p->msgstate = -1;
13022 
13023             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13024             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13025             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13026 
13027             analog_config_complete(analog_p);
13028          }
13029          break;
13030       }
13031 #if defined(HAVE_PRI)
13032       if (tmp->channel == CHAN_PSEUDO) {
13033          /*
13034           * Save off pseudo channel buffer policy values for dynamic creation of
13035           * no B channel interfaces.
13036           */
13037          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13038          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13039          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13040          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13041       }
13042 #endif   /* defined(HAVE_PRI) */
13043    }
13044    if (tmp && !here) {
13045       /* Add the new channel interface to the sorted channel interface list. */
13046       dahdi_iflist_insert(tmp);
13047    }
13048    return tmp;
13049 }

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

Definition at line 480 of file chan_dahdi.c.

Referenced by add_peer_mwi_subs(), build_peer(), config_line(), and skinny_register().

00481 {
00482    /* This module does not handle MWI in an event-based manner.  However, it
00483     * subscribes to MWI for each mailbox that is configured so that the core
00484     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00485     * event cache instead of checking the mailbox directly. */
00486 }

static int mwi_send_init ( struct dahdi_pvt pvt  )  [static]

Definition at line 11105 of file chan_dahdi.c.

References ast_callerid_vmwi_generate(), 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, has_voicemail(), MAX_CALLERID_SIZE, MWI_SEND_SA, MWI_SEND_SPILL, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisend_fsk, dahdi_pvt::mwisend_rpas, dahdi_pvt::mwisendactive, SUB_REAL, and dahdi_pvt::subs.

11106 {
11107    int x;
11108 
11109 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11110    /* Determine how this spill is to be sent */
11111    if (pvt->mwisend_rpas) {
11112       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11113       pvt->mwisendactive = 1;
11114    } else if (pvt->mwisend_fsk) {
11115       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11116       pvt->mwisendactive = 1;
11117    } else {
11118       pvt->mwisendactive = 0;
11119       return 0;
11120    }
11121 #else
11122    if (mwisend_rpas) {
11123       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11124    } else {
11125       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11126    }
11127    pvt->mwisendactive = 1;
11128 #endif
11129 
11130    if (pvt->cidspill) {
11131       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11132       ast_free(pvt->cidspill);
11133       pvt->cidspill = NULL;
11134       pvt->cidpos = 0;
11135       pvt->cidlen = 0;
11136    }
11137    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11138    if (!pvt->cidspill) {
11139       pvt->mwisendactive = 0;
11140       return -1;
11141    }
11142    x = DAHDI_FLUSH_BOTH;
11143    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11144    x = 3000;
11145    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11146 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11147    if (pvt->mwisend_fsk) {
11148 #endif
11149       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11150                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11151       pvt->cidpos = 0;
11152 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11153    }
11154 #endif
11155    return 0;
11156 }

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

Definition at line 11158 of file chan_dahdi.c.

References AS_RP_cadence, ast_free, ast_log(), dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), errno, 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::mwisend_fsk, dahdi_pvt::mwisendactive, mwisend_info::pause, SUB_REAL, and dahdi_pvt::subs.

11159 {
11160    struct timeval    now;
11161    int         res;
11162 
11163    /* sanity check to catch if this had been interrupted previously
11164    *  i.e. state says there is more to do but there is no spill allocated
11165    */
11166    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11167       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11168    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11169       /* Normal processing -- Perform mwi send action */
11170       switch ( pvt->mwisend_data.mwisend_current) {
11171       case MWI_SEND_SA:
11172          /* Send the Ring Pulse Signal Alert */
11173          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11174          if (res) {
11175             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11176             goto quit;
11177          }
11178          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11179          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11180          break;
11181       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11182          break;
11183       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11184 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11185          if (pvt->mwisend_fsk) {
11186 #endif
11187             gettimeofday(&now, NULL);
11188             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11189                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11190             }
11191 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11192          } else { /* support for mwisendtype=nofsk */
11193             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11194          }
11195 #endif
11196          break;
11197       case MWI_SEND_SPILL:
11198          /* We read some number of bytes.  Write an equal amount of data */
11199          if(0 < num_read) {
11200             if (num_read > pvt->cidlen - pvt->cidpos)
11201                num_read = pvt->cidlen - pvt->cidpos;
11202             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11203             if (res > 0) {
11204                pvt->cidpos += res;
11205                if (pvt->cidpos >= pvt->cidlen) {
11206                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11207                }
11208             } else {
11209                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11210                goto quit;
11211             }
11212          }
11213          break;
11214       case MWI_SEND_CLEANUP:
11215          /* For now, do nothing */
11216          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11217          break;
11218       default:
11219          /* Should not get here, punt*/
11220          goto quit;
11221       }
11222    }
11223 
11224    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11225       if (pvt->cidspill) {
11226          ast_free(pvt->cidspill);
11227          pvt->cidspill = NULL;
11228          pvt->cidpos = 0;
11229          pvt->cidlen = 0;
11230       }
11231       pvt->mwisendactive = 0;
11232    }
11233    return 0;
11234 quit:
11235    if (pvt->cidspill) {
11236       ast_free(pvt->cidspill);
11237       pvt->cidspill = NULL;
11238       pvt->cidpos = 0;
11239       pvt->cidlen = 0;
11240    }
11241    pvt->mwisendactive = 0;
11242    return -1;
11243 }

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

Definition at line 11245 of file chan_dahdi.c.

References ast_free, ast_log(), dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), errno, 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.

11246 {
11247    int handled = 0;
11248 
11249    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11250       switch (event) {
11251       case DAHDI_EVENT_RINGEROFF:
11252          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11253             handled = 1;
11254 
11255             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11256                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11257                ast_free(pvt->cidspill);
11258                pvt->cidspill = NULL;
11259                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11260                pvt->mwisendactive = 0;
11261             } else {
11262                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11263                gettimeofday(&pvt->mwisend_data.pause, NULL);
11264             }
11265          }
11266          break;
11267       /* Going off hook, I need to punt this spill */
11268       case DAHDI_EVENT_RINGOFFHOOK:
11269          if (pvt->cidspill) {
11270             ast_free(pvt->cidspill);
11271             pvt->cidspill = NULL;
11272             pvt->cidpos = 0;
11273             pvt->cidlen = 0;
11274          }
11275          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11276          pvt->mwisendactive = 0;
11277          break;
11278       case DAHDI_EVENT_RINGERON:
11279       case DAHDI_EVENT_HOOKCOMPLETE:
11280          break;
11281       default:
11282          break;
11283       }
11284    }
11285    return handled;
11286 }

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

Definition at line 10949 of file chan_dahdi.c.

References analog_lib_handles(), analog_ss_thread(), analog_ss_thread_start(), ast_hangup(), AST_LAW, ast_log(), ast_pthread_create_detached, AST_STATE_RING, mwi_thread_data::buf, bump_gains(), calc_energy(), callerid_feed(), callerid_free(), callerid_new(), dahdi_pvt::channel, dahdi_pvt::cid_signalling, dahdi_get_event(), dahdi_new(), errno, event2str(), get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::inalarm, analog_pvt::inalarm, mwi_thread_data::len, LOG_NOTICE, mwilevel, dahdi_pvt::mwimonitoractive, name, dahdi_pvt::oprmode, mwi_thread_data::pvt, dahdi_pvt::radio, restore_gains(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.

10950 {
10951    struct mwi_thread_data *mtd = data;
10952    struct callerid_state *cs;
10953    pthread_t threadid;
10954    int samples = 0;
10955    char *name, *number;
10956    int flags;
10957    int i, res;
10958    unsigned int spill_done = 0;
10959    int spill_result = -1;
10960 
10961    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
10962       mtd->pvt->mwimonitoractive = 0;
10963 
10964       return NULL;
10965    }
10966 
10967    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
10968 
10969    bump_gains(mtd->pvt);
10970 
10971    for (;;) {
10972       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10973       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
10974          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10975          goto quit;
10976       }
10977 
10978       if (i & DAHDI_IOMUX_SIGEVENT) {
10979          struct ast_channel *chan;
10980 
10981          /* If we get an event, screen out events that we do not act on.
10982           * Otherwise, cancel and go to the simple switch to let it deal with it.
10983           */
10984          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
10985 
10986          switch (res) {
10987          case DAHDI_EVENT_NEONMWI_ACTIVE:
10988          case DAHDI_EVENT_NEONMWI_INACTIVE:
10989          case DAHDI_EVENT_NONE:
10990          case DAHDI_EVENT_BITSCHANGED:
10991             break;
10992          case DAHDI_EVENT_NOALARM:
10993             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10994                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10995 
10996                analog_p->inalarm = 0;
10997             }
10998             mtd->pvt->inalarm = 0;
10999             handle_clear_alarms(mtd->pvt);
11000             break;
11001          case DAHDI_EVENT_ALARM:
11002             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11003                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11004 
11005                analog_p->inalarm = 1;
11006             }
11007             mtd->pvt->inalarm = 1;
11008             res = get_alarms(mtd->pvt);
11009             handle_alarms(mtd->pvt, res);
11010             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11011          default:
11012             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
11013             callerid_free(cs);
11014 
11015             restore_gains(mtd->pvt);
11016             mtd->pvt->ringt = mtd->pvt->ringt_base;
11017 
11018             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11019                int result;
11020                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11021                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11022                } else {
11023                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11024                }
11025                if (result) {
11026                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11027                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11028                   if (res < 0)
11029                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11030                   ast_hangup(chan);
11031                   goto quit;
11032                }
11033                goto quit_no_clean;
11034 
11035             } else {
11036                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11037             }
11038          }
11039       } else if (i & DAHDI_IOMUX_READ) {
11040          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11041             if (errno != ELAST) {
11042                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11043                goto quit;
11044             }
11045             break;
11046          }
11047          samples += res;
11048          if (!spill_done) {
11049             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11050                /*
11051                 * The previous diagnostic message output likely
11052                 * explains why it failed.
11053                 */
11054                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11055                break;
11056             } else if (spill_result) {
11057                spill_done = 1;
11058             }
11059          } else {
11060             /* keep reading data until the energy level drops below the threshold
11061                so we don't get another 'trigger' on the remaining carrier signal
11062             */
11063             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11064                break;
11065          }
11066          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11067             break;
11068       }
11069    }
11070 
11071    if (spill_result == 1) {
11072       callerid_get(cs, &name, &number, &flags);
11073       if (flags & CID_MSGWAITING) {
11074          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11075          notify_message(mtd->pvt->mailbox, 1);
11076       } else if (flags & CID_NOMSGWAITING) {
11077          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11078          notify_message(mtd->pvt->mailbox, 0);
11079       } else {
11080          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11081       }
11082    }
11083 
11084 
11085 quit:
11086    callerid_free(cs);
11087 
11088    restore_gains(mtd->pvt);
11089 
11090 quit_no_clean:
11091    mtd->pvt->mwimonitoractive = 0;
11092 
11093    ast_free(mtd);
11094 
11095    return NULL;
11096 }

static void my_all_subchannels_hungup ( void *  pvt  )  [static]

Definition at line 2400 of file chan_dahdi.c.

References ast_dsp_free(), ast_log(), dahdi_pvt::channel, dahdi_setlinear(), dahdi_pvt::didtdd, dahdi_pvt::dsp, errno, dahdi_pvt::faxhandled, dahdi_pvt::law, dahdi_pvt::law_default, LOG_WARNING, num_restart_pending, dahdi_subchannel::owner, dahdi_pvt::owner, reset_conf(), restart_monitor(), SUB_REAL, and dahdi_pvt::subs.

02401 {
02402    struct dahdi_pvt *p = pvt;
02403    int res, law;
02404 
02405    p->faxhandled = 0;
02406    p->didtdd = 0;
02407 
02408    if (p->dsp) {
02409       ast_dsp_free(p->dsp);
02410       p->dsp = NULL;
02411    }
02412 
02413    p->law = p->law_default;
02414    law = p->law_default;
02415    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02416    if (res < 0)
02417       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02418 
02419    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02420 
02421 #if 1
02422    {
02423    int i;
02424    p->owner = NULL;
02425    /* Cleanup owners here */
02426    for (i = 0; i < 3; i++) {
02427       p->subs[i].owner = NULL;
02428    }
02429    }
02430 #endif
02431 
02432    reset_conf(p);
02433    if (num_restart_pending == 0) {
02434       restart_monitor();
02435    }
02436 }

static int my_allocate_sub ( void *  pvt,
enum analog_sub  analogsub 
) [static]

Definition at line 2678 of file chan_dahdi.c.

References alloc_sub(), and analogsub_to_dahdisub().

02679 {
02680    struct dahdi_pvt *p = pvt;
02681 
02682    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02683 }

static void my_ami_channel_event ( void *  pvt,
struct ast_channel chan 
) [static]

Definition at line 2175 of file chan_dahdi.c.

References dahdi_ami_channel_event().

02176 {
02177    struct dahdi_pvt *p = pvt;
02178 
02179    dahdi_ami_channel_event(p, chan);
02180 }

static void my_answer_polarityswitch ( void *  pvt  )  [static]

Definition at line 2916 of file chan_dahdi.c.

References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().

02917 {
02918    struct dahdi_pvt *p = pvt;
02919 
02920    if (!p->answeronpolarityswitch) {
02921       return;
02922    }
02923 
02924    my_set_polarity(pvt, 1);
02925 }

static int my_callwait ( void *  pvt  )  [static]

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

01905 {
01906    struct dahdi_pvt *p = pvt;
01907    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01908    if (p->cidspill) {
01909       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01910       ast_free(p->cidspill);
01911    }
01912 
01913    /*
01914     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01915     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01916     */
01917    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01918       return -1;
01919    save_conference(p);
01920    /* Silence */
01921    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01922    if (!p->callwaitrings && p->callwaitingcallerid) {
01923       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01924       p->callwaitcas = 1;
01925       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01926    } else {
01927       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01928       p->callwaitcas = 0;
01929       p->cidlen = 2400 + READ_SIZE * 4;
01930    }
01931    p->cidpos = 0;
01932    send_callerid(p);
01933 
01934    return 0;
01935 }

static void my_cancel_cidspill ( void *  pvt  )  [static]

Definition at line 2350 of file chan_dahdi.c.

References ast_free, dahdi_pvt::cidspill, and restore_conference().

02351 {
02352    struct dahdi_pvt *p = pvt;
02353 
02354    ast_free(p->cidspill);
02355    p->cidspill = NULL;
02356    restore_conference(p);
02357 }

static int my_check_confirmanswer ( void *  pvt  )  [static]

Definition at line 2333 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

02334 {
02335    struct dahdi_pvt *p = pvt;
02336    if (p->confirmanswer) {
02337       return 1;
02338    }
02339 
02340    return 0;
02341 }

static int my_check_for_conference ( void *  pvt  )  [static]

Definition at line 2510 of file chan_dahdi.c.

References check_for_conference().

02511 {
02512    struct dahdi_pvt *p = pvt;
02513    return check_for_conference(p);
02514 }

static int my_check_waitingfordt ( void *  pvt  )  [static]

Definition at line 2316 of file chan_dahdi.c.

References dahdi_pvt::waitingfordt.

02317 {
02318    struct dahdi_pvt *p = pvt;
02319 
02320    if (p->waitingfordt.tv_usec) {
02321       return 1;
02322    }
02323 
02324    return 0;
02325 }

static int my_complete_conference_update ( void *  pvt,
int  needconference 
) [static]

Definition at line 2460 of file chan_dahdi.c.

References conf_add(), GET_CHANNEL, isslavenative(), MAX_SLAVES, dahdi_pvt::slaves, SUB_REAL, and dahdi_pvt::subs.

02461 {
02462    struct dahdi_pvt *p = pvt;
02463    int needconf = needconference;
02464    int x;
02465    int useslavenative;
02466    struct dahdi_pvt *slave = NULL;
02467 
02468    useslavenative = isslavenative(p, &slave);
02469 
02470    /* If we have a slave, add him to our conference now. or DAX
02471       if this is slave native */
02472    for (x = 0; x < MAX_SLAVES; x++) {
02473       if (p->slaves[x]) {
02474          if (useslavenative)
02475             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02476          else {
02477             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02478             needconf++;
02479          }
02480       }
02481    }
02482    /* If we're supposed to be in there, do so now */
02483    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02484       if (useslavenative)
02485          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02486       else {
02487          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02488          needconf++;
02489       }
02490    }
02491    /* If we have a master, add ourselves to his conference */
02492    if (p->master) {
02493       if (isslavenative(p->master, NULL)) {
02494          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02495       } else {
02496          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02497       }
02498    }
02499    if (!needconf) {
02500       /* Nobody is left (or should be left) in our conference.
02501          Kill it. */
02502       p->confno = -1;
02503    }
02504 
02505    return 0;
02506 }

static int my_conf_add ( void *  pvt,
enum analog_sub  sub 
) [static]

Definition at line 2450 of file chan_dahdi.c.

References analogsub_to_dahdisub(), conf_add(), and dahdi_pvt::subs.

02451 {
02452    struct dahdi_pvt *p = pvt;
02453    int x = analogsub_to_dahdisub(sub);
02454 
02455    return conf_add(p, &p->subs[x], x, 0);
02456 }

static int my_conf_del ( void *  pvt,
enum analog_sub  sub 
) [static]

Definition at line 2440 of file chan_dahdi.c.

References analogsub_to_dahdisub(), conf_del(), and dahdi_pvt::subs.

02441 {
02442    struct dahdi_pvt *p = pvt;
02443    int x = analogsub_to_dahdisub(sub);
02444 
02445    return conf_del(p, &p->subs[x], x);
02446 }

static int my_confmute ( void *  pvt,
int  mute 
) [static]

Definition at line 2359 of file chan_dahdi.c.

References dahdi_confmute().

02360 {
02361    struct dahdi_pvt *p = pvt;
02362    return dahdi_confmute(p, mute);
02363 }

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

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

09225 {
09226    int sent=0;
09227    int size;
09228    int res;
09229    int fd;
09230    fd = p->subs[idx].dfd;
09231    while (len) {
09232       size = len;
09233       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09234          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09235       res = write(fd, buf, size);
09236       if (res != size) {
09237          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09238          return sent;
09239       }
09240       len -= size;
09241       buf += size;
09242    }
09243    return sent;
09244 }

static void my_deadlock_avoidance_private ( void *  pvt  )  [static]

Definition at line 2122 of file chan_dahdi.c.

References DEADLOCK_AVOIDANCE, and dahdi_pvt::lock.

02123 {
02124    struct dahdi_pvt *p = pvt;
02125 
02126    DEADLOCK_AVOIDANCE(&p->lock);
02127 }

static void my_decrease_ss_count ( void   )  [static]

Definition at line 2392 of file chan_dahdi.c.

References ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, ss_thread_complete, ss_thread_count, and ss_thread_lock.

static int my_dial_digits ( void *  pvt,
enum analog_sub  sub,
struct analog_dialoperation dop 
) [static]

Definition at line 2950 of file chan_dahdi.c.

References ANALOG_DIAL_OP_REPLACE, ANALOG_SUB_REAL, analogsub_to_dahdisub(), ast_copy_string(), ast_debug, ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, analog_dialoperation::dialstr, errno, LOG_ERROR, ast_channel::name, analog_dialoperation::op, dahdi_pvt::owner, and dahdi_pvt::subs.

02951 {
02952    int index = analogsub_to_dahdisub(sub);
02953    int res;
02954    struct dahdi_pvt *p = pvt;
02955    struct dahdi_dialoperation ddop;
02956 
02957    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02958       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02959       return -1;
02960    }
02961 
02962    if (sub != ANALOG_SUB_REAL) {
02963       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
02964          dop->dialstr, p->channel, sub);
02965       return -1;
02966    }
02967 
02968    ddop.op = DAHDI_DIAL_OP_REPLACE;
02969    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
02970 
02971    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
02972 
02973    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
02974    if (res == -1) {
02975       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
02976    }
02977 
02978    return res;
02979 }

static int my_distinctive_ring ( struct ast_channel chan,
void *  pvt,
int  idx,
int *  ringdata 
) [static]

Definition at line 1768 of file chan_dahdi.c.

References ast_copy_string(), ast_hangup(), ast_log(), ast_verb, ast_channel::context, dahdi_pvt::context, dahdi_get_event(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, errno, event2str(), analog_pvt::inalarm, dahdi_pvt::inalarm, LOG_NOTICE, LOG_WARNING, RING_PATTERNS, analog_pvt::ringt, analog_pvt::ringt_base, dahdi_pvt::sig_pvt, and dahdi_pvt::subs.

01769 {
01770    unsigned char buf[256];
01771    int distMatches;
01772    int curRingData[RING_PATTERNS];
01773    int receivedRingT;
01774    int counter1;
01775    int counter;
01776    int i;
01777    int res;
01778    int checkaftercid = 0;
01779 
01780    struct dahdi_pvt *p = pvt;
01781    struct analog_pvt *analog_p = p->sig_pvt;
01782 
01783    if (ringdata == NULL) {
01784       ringdata = curRingData;
01785    } else {
01786       checkaftercid = 1;
01787    }
01788 
01789    /* We must have a ring by now, so, if configured, lets try to listen for
01790     * distinctive ringing */
01791    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01792       /* Clear the current ring data array so we don't have old data in it. */
01793       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01794          ringdata[receivedRingT] = 0;
01795       receivedRingT = 0;
01796       if (checkaftercid && distinctiveringaftercid)
01797          ast_verb(3, "Detecting post-CID distinctive ring\n");
01798       /* Check to see if context is what it should be, if not set to be. */
01799       else if (strcmp(p->context,p->defcontext) != 0) {
01800          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01801          ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01802       }
01803 
01804       for (;;) {
01805          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01806          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01807             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01808             ast_hangup(chan);
01809             return 1;
01810          }
01811          if (i & DAHDI_IOMUX_SIGEVENT) {
01812             res = dahdi_get_event(p->subs[idx].dfd);
01813             if (res == DAHDI_EVENT_NOALARM) {
01814                p->inalarm = 0;
01815                analog_p->inalarm = 0;
01816             }
01817             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01818             res = 0;
01819             /* Let us detect distinctive ring */
01820 
01821             ringdata[receivedRingT] = analog_p->ringt;
01822 
01823             if (analog_p->ringt < analog_p->ringt_base/2)
01824                break;
01825             /* Increment the ringT counter so we can match it against
01826                values in chan_dahdi.conf for distinctive ring */
01827             if (++receivedRingT == RING_PATTERNS)
01828                break;
01829          } else if (i & DAHDI_IOMUX_READ) {
01830             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01831             if (res < 0) {
01832                if (errno != ELAST) {
01833                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01834                   ast_hangup(chan);
01835                   return 1;
01836                }
01837                break;
01838             }
01839             if (analog_p->ringt > 0) {
01840                if (!(--analog_p->ringt)) {
01841                   res = -1;
01842                   break;
01843                }
01844             }
01845          }
01846       }
01847    }
01848    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01849       /* this only shows up if you have n of the dring patterns filled in */
01850       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01851       for (counter = 0; counter < 3; counter++) {
01852       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01853          distMatches = 0;
01854          /* this only shows up if you have n of the dring patterns filled in */
01855          ast_verb(3, "Checking %d,%d,%d\n",
01856                p->drings.ringnum[counter].ring[0],
01857                p->drings.ringnum[counter].ring[1],
01858                p->drings.ringnum[counter].ring[2]);
01859          for (counter1 = 0; counter1 < 3; counter1++) {
01860             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01861             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01862                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01863                ringdata[counter1]);
01864                distMatches++;
01865             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01866                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01867                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01868                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01869                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01870                distMatches++;
01871             }
01872          }
01873 
01874          if (distMatches == 3) {
01875             /* The ring matches, set the context to whatever is for distinctive ring.. */
01876             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01877             ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01878             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01879             break;
01880          }
01881       }
01882    }
01883    /* Restore linear mode (if appropriate) for Caller*ID processing */
01884    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01885    restore_gains(p);
01886 
01887    return 0;
01888 }

static int my_dsp_reset_and_flush_digits ( void *  pvt  )  [static]

Definition at line 1972 of file chan_dahdi.c.

References ast_dsp_digitreset(), and dahdi_pvt::dsp.

01973 {
01974    struct dahdi_pvt *p = pvt;
01975    if (p->dsp)
01976       ast_dsp_digitreset(p->dsp);
01977 
01978    return 0;
01979 }

static int my_dsp_set_digitmode ( void *  pvt,
enum analog_dsp_digitmode  mode 
) [static]

Definition at line 1981 of file chan_dahdi.c.

References ANALOG_DIGITMODE_DTMF, ANALOG_DIGITMODE_MF, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_digitmode(), ast_log(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, dahdi_pvt::hardwaredtmf, and LOG_ERROR.

01982 {
01983    struct dahdi_pvt *p = pvt;
01984 
01985    if (p->channel == CHAN_PSEUDO)
01986       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
01987 
01988    if (mode == ANALOG_DIGITMODE_DTMF) {
01989       /* If we do hardware dtmf, no need for a DSP */
01990       if (p->hardwaredtmf) {
01991          if (p->dsp) {
01992             ast_dsp_free(p->dsp);
01993             p->dsp = NULL;
01994          }
01995          return 0;
01996       }
01997 
01998       if (!p->dsp) {
01999          p->dsp = ast_dsp_new();
02000          if (!p->dsp) {
02001             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02002             return -1;
02003          }
02004       }
02005 
02006       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02007    } else if (mode == ANALOG_DIGITMODE_MF) {
02008       if (!p->dsp) {
02009          p->dsp = ast_dsp_new();
02010          if (!p->dsp) {
02011             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02012             return -1;
02013          }
02014       }
02015       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02016    }
02017    return 0;
02018 }

static int my_flash ( void *  pvt  )  [static]

Definition at line 2875 of file chan_dahdi.c.

References SUB_REAL, and dahdi_pvt::subs.

02876 {
02877    struct dahdi_pvt *p = pvt;
02878    int func = DAHDI_FLASH;
02879    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02880 }

static void my_get_and_handle_alarms ( void *  pvt  )  [static]

Definition at line 2208 of file chan_dahdi.c.

References get_alarms(), and handle_alarms().

02209 {
02210    int res;
02211    struct dahdi_pvt *p = pvt;
02212 
02213    res = get_alarms(p);
02214    handle_alarms(p, res);
02215 }

static int my_get_callerid ( void *  pvt,
char *  namebuf,
char *  numbuf,
enum analog_event ev,
size_t  timeout 
) [static]

Definition at line 1691 of file chan_dahdi.c.

References ANALOG_EVENT_NONE, ANALOG_MAX_CID, ast_copy_string(), AST_LAW, ast_log(), callerid_feed(), callerid_feed_jp(), callerid_free(), callerid_get(), CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cs, dahdi_get_event(), dahdievent_to_analogevent(), dahdi_subchannel::dfd, errno, LOG_DEBUG, LOG_WARNING, name, analog_pvt::ringt, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.

01692 {
01693    struct dahdi_pvt *p = pvt;
01694    struct analog_pvt *analog_p = p->sig_pvt;
01695    struct pollfd poller;
01696    char *name, *num;
01697    int index = SUB_REAL;
01698    int res;
01699    unsigned char buf[256];
01700    int flags;
01701 
01702    poller.fd = p->subs[SUB_REAL].dfd;
01703    poller.events = POLLPRI | POLLIN;
01704    poller.revents = 0;
01705 
01706    res = poll(&poller, 1, timeout);
01707 
01708    if (poller.revents & POLLPRI) {
01709       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01710       return 1;
01711    }
01712 
01713    if (poller.revents & POLLIN) {
01714       /*** NOTES ***/
01715       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01716        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01717        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01718        * a failure and die, and returning 2 means no event was received. */
01719       res = read(p->subs[index].dfd, buf, sizeof(buf));
01720       if (res < 0) {
01721          if (errno != ELAST) {
01722             ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01723             callerid_free(p->cs);
01724             return -1;
01725          }
01726       }
01727 
01728       if (analog_p->ringt > 0) {
01729          if (!(--analog_p->ringt)) {
01730             /* only return if we timeout from a ring event */
01731             return -1;
01732          }
01733       }
01734 
01735       if (p->cid_signalling == CID_SIG_V23_JP) {
01736          res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01737       } else {
01738          res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01739       }
01740       if (res < 0) {
01741          /*
01742           * The previous diagnostic message output likely
01743           * explains why it failed.
01744           */
01745          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01746          return -1;
01747       }
01748 
01749       if (res == 1) {
01750          callerid_get(p->cs, &name, &num, &flags);
01751          if (name)
01752             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01753          if (num)
01754             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01755 
01756          ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01757          return 0;
01758       }
01759    }
01760 
01761    *ev = ANALOG_EVENT_NONE;
01762    return 2;
01763 }

static int my_get_event ( void *  pvt  )  [static]

Definition at line 2808 of file chan_dahdi.c.

References dahdi_get_event(), dahdievent_to_analogevent(), dahdi_pvt::fake_event, SUB_REAL, and dahdi_pvt::subs.

02809 {
02810    struct dahdi_pvt *p = pvt;
02811    int res;
02812 
02813    if (p->fake_event) {
02814       res = p->fake_event;
02815       p->fake_event = 0;
02816    } else
02817       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02818 
02819    return dahdievent_to_analogevent(res);
02820 }

static const char* my_get_orig_dialstring ( void *  pvt  )  [static]

Definition at line 2378 of file chan_dahdi.c.

References dahdi_pvt::dialstring.

02379 {
02380    struct dahdi_pvt *p = pvt;
02381 
02382    return p->dialstring;
02383 }

static void* my_get_sigpvt_bridged_channel ( struct ast_channel chan  )  [static]

Definition at line 2217 of file chan_dahdi.c.

References ast_bridged_channel(), dahdi_pvt::sig_pvt, and ast_channel::tech_pvt.

02218 {
02219    struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02220    if (p)
02221       return p->sig_pvt;
02222    else
02223       return NULL;
02224 }

static int my_get_sub_fd ( void *  pvt,
enum analog_sub  sub 
) [static]

Definition at line 2226 of file chan_dahdi.c.

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

02227 {
02228    struct dahdi_pvt *p = pvt;
02229    int dahdi_sub = analogsub_to_dahdisub(sub);
02230    return p->subs[dahdi_sub].dfd;
02231 }

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

Definition at line 9705 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by analog_ss_thread().

09706 {
09707    char c;
09708 
09709    *str = 0; /* start with empty output buffer */
09710    for (;;)
09711    {
09712       /* Wait for the first digit (up to specified ms). */
09713       c = ast_waitfordigit(chan, ms);
09714       /* if timeout, hangup or error, return as such */
09715       if (c < 1)
09716          return c;
09717       *str++ = c;
09718       *str = 0;
09719       if (strchr(term, c))
09720          return 1;
09721    }
09722 }

static void my_handle_dchan_exception ( struct sig_pri_span pri,
int  index 
) [static]

Definition at line 3073 of file chan_dahdi.c.

References ast_log(), event2str(), sig_pri_span::fds, LOG_NOTICE, dahdi_pvt::pri, pri_event_alarm(), pri_event_noalarm(), and sig_pri_span::span.

03074 {
03075    int x;
03076 
03077    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03078    if (x) {
03079       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
03080    }
03081    /* Keep track of alarm state */
03082    switch (x) {
03083    case DAHDI_EVENT_ALARM:
03084       pri_event_alarm(pri, index, 0);
03085       break;
03086    case DAHDI_EVENT_NOALARM:
03087       pri_event_noalarm(pri, index, 0);
03088       break;
03089    default:
03090       break;
03091    }
03092 }

static void my_handle_dtmf ( void *  pvt,
struct ast_channel ast,
enum analog_sub  analog_index,
struct ast_frame **  dest 
) [static]

Definition at line 2038 of file chan_dahdi.c.

References analogsub_to_dahdisub(), ast_async_goto(), ast_channel_lock, ast_channel_unlock, ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verb, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, ast_channel::caller, dahdi_pvt::callprogress, CALLPROGRESS_FAX, ast_channel::context, dahdi_confmute(), dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, errno, ast_channel::exten, dahdi_subchannel::f, f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxhandled, ast_frame::frametype, ast_party_caller::id, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, ast_channel::name, ast_party_id::number, pbx_builtin_setvar_helper(), S_COR, S_OR, ast_party_number::str, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::usefaxbuffers, and ast_party_number::valid.

02039 {
02040    struct ast_frame *f = *dest;
02041    struct dahdi_pvt *p = pvt;
02042    int idx = analogsub_to_dahdisub(analog_index);
02043 
02044    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02045       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02046       f->subclass.integer, f->subclass.integer, ast->name);
02047 
02048    if (f->subclass.integer == 'f') {
02049       if (f->frametype == AST_FRAME_DTMF_END) {
02050          /* Fax tone -- Handle and return NULL */
02051          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02052             /* If faxbuffers are configured, use them for the fax transmission */
02053             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02054                struct dahdi_bufferinfo bi = {
02055                   .txbufpolicy = p->faxbuf_policy,
02056                   .bufsize = p->bufsize,
02057                   .numbufs = p->faxbuf_no
02058                };
02059                int res;
02060 
02061                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02062                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02063                } else {
02064                   p->bufferoverrideinuse = 1;
02065                }
02066             }
02067             p->faxhandled = 1;
02068             if (p->dsp) {
02069                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02070                ast_dsp_set_features(p->dsp, p->dsp_features);
02071                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02072             }
02073             if (strcmp(ast->exten, "fax")) {
02074                const char *target_context = S_OR(ast->macrocontext, ast->context);
02075 
02076                /* We need to unlock 'ast' here because ast_exists_extension has the
02077                 * potential to start autoservice on the channel. Such action is prone
02078                 * to deadlock.
02079                 */
02080                ast_mutex_unlock(&p->lock);
02081                ast_channel_unlock(ast);
02082                if (ast_exists_extension(ast, target_context, "fax", 1,
02083                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02084                   ast_channel_lock(ast);
02085                   ast_mutex_lock(&p->lock);
02086                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02087                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02088                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02089                   if (ast_async_goto(ast, target_context, "fax", 1))
02090                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02091                } else {
02092                   ast_channel_lock(ast);
02093                   ast_mutex_lock(&p->lock);
02094                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02095                }
02096             } else {
02097                ast_debug(1, "Already in a fax extension, not redirecting\n");
02098             }
02099          } else {
02100             ast_debug(1, "Fax already handled\n");
02101          }
02102          dahdi_confmute(p, 0);
02103       }
02104       p->subs[idx].f.frametype = AST_FRAME_NULL;
02105       p->subs[idx].f.subclass.integer = 0;
02106       *dest = &p->subs[idx].f;
02107    }
02108 }

static void my_handle_link_exception ( struct sig_ss7_linkset linkset,
int  which 
) [static]

Definition at line 3381 of file chan_dahdi.c.

References ast_log(), event2str(), sig_ss7_linkset::fds, LOG_ERROR, LOG_NOTICE, sig_ss7_link_alarm(), sig_ss7_link_noalarm(), and sig_ss7_linkset::span.

03382 {
03383    int event;
03384 
03385    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03386       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03387          linkset->span, which);
03388       return;
03389    }
03390    switch (event) {
03391    case DAHDI_EVENT_NONE:
03392       break;
03393    case DAHDI_EVENT_ALARM:
03394       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03395          event2str(event), event, linkset->span, which);
03396       sig_ss7_link_alarm(linkset, which);
03397       break;
03398    case DAHDI_EVENT_NOALARM:
03399       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03400          event2str(event), event, linkset->span, which);
03401       sig_ss7_link_noalarm(linkset, which);
03402       break;
03403    default:
03404       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03405          event2str(event), event, linkset->span, which);
03406       break;
03407    }
03408 }

static void my_handle_notify_message ( struct ast_channel chan,
void *  pvt,
int  cid_flags,
int  neon_mwievent 
) [static]

Definition at line 3577 of file chan_dahdi.c.

References ANALOG_EVENT_NEONMWI_ACTIVE, ANALOG_EVENT_NEONMWI_INACTIVE, ast_hangup(), ast_log(), dahdi_pvt::channel, CID_MSGWAITING, CID_NOMSGWAITING, LOG_NOTICE, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, and notify_message().

03578 {
03579    struct dahdi_pvt *p = pvt;
03580 
03581    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03582       return;
03583 
03584    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03585       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03586       notify_message(p->mailbox, 1);
03587    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03588       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03589       notify_message(p->mailbox, 0);
03590    }
03591    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03592    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03593    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03594       ast_hangup(chan);
03595       return;
03596    }
03597 }

static void my_hangup_polarityswitch ( void *  pvt  )  [static]

Definition at line 2927 of file chan_dahdi.c.

References dahdi_pvt::answeronpolarityswitch, dahdi_pvt::hanguponpolarityswitch, and my_set_polarity().

02928 {
02929    struct dahdi_pvt *p = pvt;
02930 
02931    if (!p->hanguponpolarityswitch) {
02932       return;
02933    }
02934 
02935    if (p->answeronpolarityswitch) {
02936       my_set_polarity(pvt, 0);
02937    } else {
02938       my_set_polarity(pvt, 1);
02939    }
02940 }

static int my_has_voicemail ( void *  pvt  )  [static]

Definition at line 2687 of file chan_dahdi.c.

References has_voicemail().

02688 {
02689    struct dahdi_pvt *p = pvt;
02690 
02691    return has_voicemail(p);
02692 }

static int my_have_progressdetect ( void *  pvt  )  [static]

Definition at line 3599 of file chan_dahdi.c.

References dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, CANPROGRESSDETECT, dahdi_pvt::dsp, and dahdi_pvt::outgoing.

03600 {
03601    struct dahdi_pvt *p = pvt;
03602 
03603    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03604       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03605       return 1;
03606    } else {
03607       /* Don't have progress detection. */
03608       return 0;
03609    }
03610 }

static void my_increase_ss_count ( void   )  [static]

Definition at line 2385 of file chan_dahdi.c.

References ast_mutex_lock, ast_mutex_unlock, ss_thread_count, and ss_thread_lock.

static int my_is_dialing ( void *  pvt,
enum analog_sub  sub 
) [static]

Definition at line 2992 of file chan_dahdi.c.

References analogsub_to_dahdisub(), ast_log(), dahdi_subchannel::dfd, LOG_DEBUG, and dahdi_pvt::subs.

02993 {
02994    struct dahdi_pvt *p = pvt;
02995    int index;
02996    int x;
02997 
02998    index = analogsub_to_dahdisub(sub);
02999 
03000    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03001       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03002       return -1;
03003    }
03004 
03005    return x;
03006 }

static int my_is_off_hook ( void *  pvt  )  [static]

Definition at line 2822 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, errno, LOG_WARNING, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SUB_REAL, and dahdi_pvt::subs.

02823 {
02824    struct dahdi_pvt *p = pvt;
02825    int res;
02826    struct dahdi_params par;
02827 
02828    memset(&par, 0, sizeof(par));
02829 
02830    if (p->subs[SUB_REAL].dfd > -1)
02831       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02832    else {
02833       /* Assume not off hook on CVRS */
02834       res = 0;
02835       par.rxisoffhook = 0;
02836    }
02837    if (res) {
02838       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02839    }
02840 
02841    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02842       /* When "onhook" that means no battery on the line, and thus
02843       it is out of service..., if it's on a TDM card... If it's a channel
02844       bank, there is no telling... */
02845       return (par.rxbits > -1) || par.rxisoffhook;
02846    }
02847 
02848    return par.rxisoffhook;
02849 }

static void my_lock_private ( void *  pvt  )  [static]

Definition at line 2110 of file chan_dahdi.c.

References ast_mutex_lock, and dahdi_pvt::lock.

02111 {
02112    struct dahdi_pvt *p = pvt;
02113    ast_mutex_lock(&p->lock);
02114 }

static void my_module_ref ( void   )  [static]

Definition at line 3314 of file chan_dahdi.c.

References ast_module_ref().

03315 {
03316    ast_module_ref(ast_module_info->self);
03317 }

static void my_module_unref ( void   )  [static]

Definition at line 3328 of file chan_dahdi.c.

References ast_module_unref().

03329 {
03330    ast_module_unref(ast_module_info->self);
03331 }

static struct ast_channel* my_new_analog_ast_channel ( void *  pvt,
int  state,
int  startpbx,
enum analog_sub  sub,
const struct ast_channel requestor 
) [static]

Definition at line 2550 of file chan_dahdi.c.

References analogsub_to_dahdisub(), dahdi_new(), and ast_channel::linkedid.

02551 {
02552    struct dahdi_pvt *p = pvt;
02553    int dsub = analogsub_to_dahdisub(sub);
02554 
02555    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02556 }

static struct ast_channel* my_new_pri_ast_channel ( void *  pvt,
int  state,
enum sig_pri_law  law,
char *  exten,
const struct ast_channel requestor 
) [static]

Definition at line 2570 of file chan_dahdi.c.

References ast_copy_string(), ast_log(), dahdi_pvt::channel, dahdi_new(), dahdi_setlaw(), errno, dahdi_pvt::exten, ast_channel::linkedid, LOG_WARNING, dahdi_pvt::sig, SIG_PRI_ALAW, SIG_PRI_DEFLAW, SIG_PRI_LIB_HANDLE_CASES, SIG_PRI_ULAW, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.

02571 {
02572    struct dahdi_pvt *p = pvt;
02573    int audio;
02574    int newlaw = -1;
02575 
02576    switch (p->sig) {
02577    case SIG_PRI_LIB_HANDLE_CASES:
02578       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02579          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02580          break;
02581       }
02582       /* Fall through */
02583    default:
02584       /* Set to audio mode at this point */
02585       audio = 1;
02586       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02587          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02588             p->channel, audio, strerror(errno));
02589       }
02590       break;
02591    }
02592 
02593    if (law != SIG_PRI_DEFLAW) {
02594       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02595    }
02596 
02597    ast_copy_string(p->exten, exten, sizeof(p->exten));
02598 
02599    switch (law) {
02600       case SIG_PRI_DEFLAW:
02601          newlaw = 0;
02602          break;
02603       case SIG_PRI_ALAW:
02604          newlaw = DAHDI_LAW_ALAW;
02605          break;
02606       case SIG_PRI_ULAW:
02607          newlaw = DAHDI_LAW_MULAW;
02608          break;
02609    }
02610    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02611 }

static struct ast_channel* my_new_ss7_ast_channel ( void *  pvt,
int  state,
enum sig_ss7_law  law,
char *  exten,
const struct ast_channel requestor 
) [static]

Definition at line 3438 of file chan_dahdi.c.

References ast_copy_string(), ast_log(), dahdi_pvt::channel, dahdi_new(), dahdi_setlaw(), errno, dahdi_pvt::exten, ast_channel::linkedid, LOG_WARNING, SIG_SS7_ALAW, SIG_SS7_DEFLAW, SIG_SS7_ULAW, SUB_REAL, and dahdi_pvt::subs.

03439 {
03440    struct dahdi_pvt *p = pvt;
03441    int audio;
03442    int newlaw;
03443 
03444    /* Set to audio mode at this point */
03445    audio = 1;
03446    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03447       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03448          p->channel, audio, strerror(errno));
03449 
03450    if (law != SIG_SS7_DEFLAW) {
03451       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03452          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03453    }
03454 
03455    ast_copy_string(p->exten, exten, sizeof(p->exten));
03456 
03457    newlaw = -1;
03458    switch (law) {
03459    case SIG_SS7_DEFLAW:
03460       newlaw = 0;
03461       break;
03462    case SIG_SS7_ALAW:
03463       newlaw = DAHDI_LAW_ALAW;
03464       break;
03465    case SIG_SS7_ULAW:
03466       newlaw = DAHDI_LAW_MULAW;
03467       break;
03468    }
03469    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03470 }

static int my_off_hook ( void *  pvt  )  [static]

Definition at line 2884 of file chan_dahdi.c.

References dahdi_set_hook(), SUB_REAL, and dahdi_pvt::subs.

02885 {
02886    struct dahdi_pvt *p = pvt;
02887    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02888 }

static int my_on_hook ( void *  pvt  )  [static]

Definition at line 3008 of file chan_dahdi.c.

References ANALOG_SUB_REAL, dahdi_set_hook(), and dahdi_pvt::subs.

03009 {
03010    struct dahdi_pvt *p = pvt;
03011    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03012 }

static int my_play_tone ( void *  pvt,
enum analog_sub  sub,
enum analog_tone  tone 
) [static]

Definition at line 2694 of file chan_dahdi.c.

References analog_tone_to_dahditone(), analogsub_to_dahdisub(), dahdi_subchannel::dfd, and dahdi_pvt::subs.

02695 {
02696    struct dahdi_pvt *p = pvt;
02697    int index;
02698 
02699    index = analogsub_to_dahdisub(sub);
02700 
02701    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02702 }

static void my_pri_fixup_chans ( void *  chan_old,
void *  chan_new 
) [static]

Definition at line 3015 of file chan_dahdi.c.

References dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dialstring, dahdi_pvt::digital, dahdi_pvt::dsp, dahdi_pvt::dsp_features, ast_channel::fds, dahdi_pvt::law, dahdi_pvt::outgoing, dahdi_subchannel::owner, dahdi_pvt::owner, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

03016 {
03017    struct dahdi_pvt *old_chan = chan_old;
03018    struct dahdi_pvt *new_chan = chan_new;
03019 
03020    new_chan->owner = old_chan->owner;
03021    old_chan->owner = NULL;
03022    if (new_chan->owner) {
03023       new_chan->owner->tech_pvt = new_chan;
03024       new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03025       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03026       old_chan->subs[SUB_REAL].owner = NULL;
03027    }
03028    /* Copy any DSP that may be present */
03029    new_chan->dsp = old_chan->dsp;
03030    new_chan->dsp_features = old_chan->dsp_features;
03031    old_chan->dsp = NULL;
03032    old_chan->dsp_features = 0;
03033 
03034    /* Transfer flags from the old channel. */
03035    new_chan->dialing = old_chan->dialing;
03036    new_chan->digital = old_chan->digital;
03037    new_chan->outgoing = old_chan->outgoing;
03038    old_chan->dialing = 0;
03039    old_chan->digital = 0;
03040    old_chan->outgoing = 0;
03041 
03042    /* More stuff to transfer to the new channel. */
03043    new_chan->law = old_chan->law;
03044    strcpy(new_chan->dialstring, old_chan->dialstring);
03045 }

static void my_pri_init_config ( void *  priv,
struct sig_pri_span pri 
) [static]

Definition at line 13151 of file chan_dahdi.c.

References ast_copy_string(), sig_pri_span::ch_cfg, sig_pri_span::context, dahdi_pvt::context, sig_pri_span::hidecallerid, dahdi_pvt::hidecallerid, sig_pri_span::hidecalleridname, dahdi_pvt::hidecalleridname, sig_pri_span::immediate, dahdi_pvt::immediate, sig_pri_span::mohinterpret, dahdi_pvt::mohinterpret, dahdi_pvt::pri, sig_pri_span::priexclusive, dahdi_pvt::priexclusive, sig_pri_span::priindication_oob, dahdi_pvt::priindication_oob, sig_pri_span::stripmsd, dahdi_pvt::stripmsd, sig_pri_span::use_callerid, dahdi_pvt::use_callerid, sig_pri_span::use_callingpres, and dahdi_pvt::use_callingpres.

13152 {
13153    struct dahdi_pvt *pvt = priv;
13154 
13155    pvt->stripmsd = pri->ch_cfg.stripmsd;
13156    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13157    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13158    pvt->immediate = pri->ch_cfg.immediate;
13159    pvt->priexclusive = pri->ch_cfg.priexclusive;
13160    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13161    pvt->use_callerid = pri->ch_cfg.use_callerid;
13162    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13163    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13164    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13165 }

static void my_pri_make_cc_dialstring ( void *  priv,
char *  buf,
size_t  buf_size 
) [static]

Definition at line 3203 of file chan_dahdi.c.

References args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_NONSTANDARD_APP_ARGS, and ast_strdupa.

03204 {
03205    char *dial;
03206    struct dahdi_pvt *pvt;
03207    AST_DECLARE_APP_ARGS(args,
03208       AST_APP_ARG(tech);   /* channel technology token */
03209       AST_APP_ARG(group);  /* channel/group token */
03210       //AST_APP_ARG(ext);  /* extension token */
03211       //AST_APP_ARG(opts); /* options token */
03212       //AST_APP_ARG(other);   /* Any remining unused arguments */
03213    );
03214 
03215    pvt = priv;
03216    dial = ast_strdupa(pvt->dialstring);
03217    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03218    if (!args.tech) {
03219       ast_copy_string(buf, pvt->dialstring, buf_size);
03220       return;
03221    }
03222    if (!args.group) {
03223       /* Append the ISDN span channel restriction to the dialstring. */
03224       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03225       return;
03226    }
03227    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03228       /* The ISDN span channel restriction is not needed or already
03229        * in the dialstring. */
03230       ast_copy_string(buf, pvt->dialstring, buf_size);
03231       return;
03232    }
03233    /* Insert the ISDN span channel restriction into the dialstring. */
03234    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03235 }

static void my_pri_open_media ( void *  p  )  [static]

Definition at line 2626 of file chan_dahdi.c.

References ast_dsp_set_features(), ast_log(), dahdi_pvt::channel, dahdi_setlaw(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dsp, dahdi_pvt::dsp_features, errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::txdrc, and dahdi_pvt::txgain.

02627 {
02628    struct dahdi_pvt *pvt = p;
02629    int res;
02630    int dfd;
02631    int set_val;
02632 
02633    dfd = pvt->subs[SUB_REAL].dfd;
02634 
02635    /* Open the media path. */
02636    set_val = 1;
02637    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02638    if (res < 0) {
02639       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02640          pvt->channel, strerror(errno));
02641    }
02642 
02643    /* Set correct companding law for this call. */
02644    res = dahdi_setlaw(dfd, pvt->law);
02645    if (res < 0) {
02646       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02647    }
02648 
02649    /* Set correct gain for this call. */
02650    if (pvt->digital) {
02651       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02652    } else {
02653       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02654          pvt->law);
02655    }
02656    if (res < 0) {
02657       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02658    }
02659 
02660    if (pvt->dsp_features && pvt->dsp) {
02661       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02662       pvt->dsp_features = 0;
02663    }
02664 }

static int my_pri_play_tone ( void *  pvt,
enum sig_pri_tone  tone 
) [static]

Definition at line 3096 of file chan_dahdi.c.

References sig_pri_tone_to_dahditone(), SUB_REAL, and dahdi_pvt::subs.

03097 {
03098    struct dahdi_pvt *p = pvt;
03099 
03100    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03101 }

static int my_ring ( void *  pvt  )  [static]

Definition at line 2868 of file chan_dahdi.c.

References dahdi_ring_phone().

02869 {
02870    struct dahdi_pvt *p = pvt;
02871 
02872    return dahdi_ring_phone(p);
02873 }

static int my_send_callerid ( void *  pvt,
int  cwcid,
struct ast_party_caller caller 
) [static]

Definition at line 1937 of file chan_dahdi.c.

References ast_callerid_callwaiting_generate(), ast_callerid_generate(), ast_debug, ast_free, AST_LAW, ast_log(), ast_malloc, ast_verb, dahdi_pvt::callwaitcas, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, ast_party_caller::id, LOG_WARNING, MAX_CALLERID_SIZE, ast_party_id::name, ast_party_id::number, READ_SIZE, send_callerid(), ast_party_number::str, and ast_party_name::str.

01938 {
01939    struct dahdi_pvt *p = pvt;
01940 
01941    ast_debug(2, "Starting cid spill\n");
01942 
01943    if (p->cidspill) {
01944       ast_log(LOG_WARNING, "cidspill already exists??\n");
01945       ast_free(p->cidspill);
01946    }
01947 
01948    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01949       if (cwcid == 0) {
01950          p->cidlen = ast_callerid_generate(p->cidspill,
01951             caller->id.name.str,
01952             caller->id.number.str,
01953             AST_LAW(p));
01954       } else {
01955          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01956             caller->id.name.str, caller->id.number.str);
01957          p->callwaitcas = 0;
01958          p->cidcwexpire = 0;
01959          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01960             caller->id.name.str,
01961             caller->id.number.str,
01962             AST_LAW(p));
01963          p->cidlen += READ_SIZE * 4;
01964       }
01965       p->cidpos = 0;
01966       p->cid_suppress_expire = 0;
01967       send_callerid(p);
01968    }
01969    return 0;
01970 }

static void my_set_alarm ( void *  pvt,
int  in_alarm 
) [static]

Definition at line 2249 of file chan_dahdi.c.

References dahdi_pvt::inalarm.

02250 {
02251    struct dahdi_pvt *p = pvt;
02252 
02253    p->inalarm = in_alarm;
02254 }

static void my_set_cadence ( void *  pvt,
int *  cidrings,
struct ast_channel ast 
) [static]

Definition at line 2233 of file chan_dahdi.c.

References ast_log(), cadences, dahdi_pvt::distinctivering, errno, LOG_WARNING, ast_channel::name, num_cadence, dahdi_pvt::sendcalleridafter, SUB_REAL, and dahdi_pvt::subs.

02234 {
02235    struct dahdi_pvt *p = pvt;
02236 
02237    /* Choose proper cadence */
02238    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02239       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02240          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02241       *cidrings = cidrings[p->distinctivering - 1];
02242    } else {
02243       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02244          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02245       *cidrings = p->sendcalleridafter;
02246    }
02247 }

static void my_set_callerid ( void *  pvt,
const struct ast_party_caller caller 
) [static]

Definition at line 3115 of file chan_dahdi.c.

References ast_party_caller::ani, ast_party_caller::ani2, ast_copy_string(), ast_party_id_presentation(), dahdi_pvt::callingpres, dahdi_pvt::cid_ani, dahdi_pvt::cid_ani2, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_tag, dahdi_pvt::cid_ton, ast_party_caller::id, ast_party_id::name, ast_party_id::number, ast_party_number::plan, S_COR, ast_party_subaddress::str, ast_party_name::str, ast_party_number::str, ast_party_id::subaddress, ast_party_id::tag, ast_party_subaddress::valid, ast_party_name::valid, and ast_party_number::valid.

03116 {
03117    struct dahdi_pvt *p = pvt;
03118 
03119    ast_copy_string(p->cid_num,
03120       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03121       sizeof(p->cid_num));
03122    ast_copy_string(p->cid_name,
03123       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03124       sizeof(p->cid_name));
03125    ast_copy_string(p->cid_subaddr,
03126       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03127       sizeof(p->cid_subaddr));
03128    p->cid_ton = caller->id.number.plan;
03129    p->callingpres = ast_party_id_presentation(&caller->id);
03130    if (caller->id.tag) {
03131       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03132    }
03133    ast_copy_string(p->cid_ani,
03134       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03135       sizeof(p->cid_ani));
03136    p->cid_ani2 = caller->ani2;
03137 }

static void my_set_callwaiting ( void *  pvt,
int  callwaiting_enable 
) [static]

Definition at line 2343 of file chan_dahdi.c.

References dahdi_pvt::callwaiting.

02344 {
02345    struct dahdi_pvt *p = pvt;
02346 
02347    p->callwaiting = callwaiting_enable;
02348 }

static void my_set_confirmanswer ( void *  pvt,
int  flag 
) [static]

Definition at line 2327 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

02328 {
02329    struct dahdi_pvt *p = pvt;
02330    p->confirmanswer = flag;
02331 }

static void my_set_dialing ( void *  pvt,
int  is_dialing 
) [static]

Definition at line 2256 of file chan_dahdi.c.

References dahdi_pvt::dialing.

02257 {
02258    struct dahdi_pvt *p = pvt;
02259 
02260    p->dialing = is_dialing;
02261 }

static void my_set_digital ( void *  pvt,
int  is_digital 
) [static]

Definition at line 2264 of file chan_dahdi.c.

References dahdi_pvt::digital.

02265 {
02266    struct dahdi_pvt *p = pvt;
02267 
02268    p->digital = is_digital;
02269 }

static void my_set_dnid ( void *  pvt,
const char *  dnid 
) [static]

Definition at line 3151 of file chan_dahdi.c.

References ast_copy_string(), and dahdi_pvt::dnid.

03152 {
03153    struct dahdi_pvt *p = pvt;
03154 
03155    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03156 }

static int my_set_echocanceller ( void *  pvt,
int  enable 
) [static]

Definition at line 2854 of file chan_dahdi.c.

References dahdi_disable_ec(), and dahdi_enable_ec().

02855 {
02856    struct dahdi_pvt *p = pvt;
02857 
02858    if (enable)
02859       dahdi_enable_ec(p);
02860    else
02861       dahdi_disable_ec(p);
02862 
02863    return 0;
02864 }

static void my_set_inservice ( void *  pvt,
int  is_inservice 
) [static]

Definition at line 2273 of file chan_dahdi.c.

References dahdi_pvt::inservice.

02274 {
02275    struct dahdi_pvt *p = pvt;
02276 
02277    p->inservice = is_inservice;
02278 }

static void my_set_inthreeway ( void *  pvt,
enum analog_sub  sub,
int  inthreeway 
) [static]

Definition at line 2198 of file chan_dahdi.c.

References analogsub_to_dahdisub(), dahdi_subchannel::inthreeway, and dahdi_pvt::subs.

02199 {
02200    struct dahdi_pvt *p = pvt;
02201    int idx = analogsub_to_dahdisub(sub);
02202 
02203    p->subs[idx].inthreeway = inthreeway;
02204 }

static int my_set_linear_mode ( void *  pvt,
enum analog_sub  sub,
int  linear_mode 
) [static]

Definition at line 2186 of file chan_dahdi.c.

References analogsub_to_dahdisub(), dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_subchannel::linear, and dahdi_pvt::subs.

02187 {
02188    struct dahdi_pvt *p = pvt;
02189    int oldval;
02190    int idx = analogsub_to_dahdisub(sub);
02191    
02192    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02193    oldval = p->subs[idx].linear;
02194    p->subs[idx].linear = linear_mode ? 1 : 0;
02195    return oldval;
02196 }

static void my_set_locallyblocked ( void *  pvt,
int  is_blocked 
) [static]

Definition at line 2282 of file chan_dahdi.c.

References dahdi_pvt::locallyblocked.

02283 {
02284    struct dahdi_pvt *p = pvt;
02285 
02286    p->locallyblocked = is_blocked;
02287 }

static void my_set_needringing ( void *  pvt,
int  value 
) [static]

Definition at line 2890 of file chan_dahdi.c.

References dahdi_subchannel::needringing, SUB_REAL, and dahdi_pvt::subs.

02891 {
02892    struct dahdi_pvt *p = pvt;
02893    p->subs[SUB_REAL].needringing = value;
02894 }

static void my_set_new_owner ( void *  pvt,
struct ast_channel new_owner 
) [static]

Definition at line 2371 of file chan_dahdi.c.

References dahdi_pvt::owner.

02372 {
02373    struct dahdi_pvt *p = pvt;
02374 
02375    p->owner = new_owner;
02376 }

static void my_set_polarity ( void *  pvt,
int  value 
) [static]

Definition at line 2896 of file chan_dahdi.c.

References CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::polarity, SUB_REAL, and dahdi_pvt::subs.

Referenced by my_answer_polarityswitch(), my_hangup_polarityswitch(), and my_start_polarityswitch().

02897 {
02898    struct dahdi_pvt *p = pvt;
02899 
02900    if (p->channel == CHAN_PSEUDO) {
02901       return;
02902    }
02903    p->polarity = value;
02904    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02905 }

static void my_set_pulsedial ( void *  pvt,
int  flag 
) [static]

Definition at line 2365 of file chan_dahdi.c.

References dahdi_pvt::pulsedial.

02366 {
02367    struct dahdi_pvt *p = pvt;
02368    p->pulsedial = flag;
02369 }

static void my_set_rdnis ( void *  pvt,
const char *  rdnis 
) [static]

Definition at line 3170 of file chan_dahdi.c.

References ast_copy_string(), and dahdi_pvt::rdnis.

03171 {
03172    struct dahdi_pvt *p = pvt;
03173 
03174    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03175 }

static void my_set_remotelyblocked ( void *  pvt,
int  is_blocked 
) [static]

Definition at line 2291 of file chan_dahdi.c.

References dahdi_pvt::remotelyblocked.

02292 {
02293    struct dahdi_pvt *p = pvt;
02294 
02295    p->remotelyblocked = is_blocked;
02296 }

static void my_set_ringtimeout ( void *  pvt,
int  ringt 
) [static]

Definition at line 2299 of file chan_dahdi.c.

References dahdi_pvt::ringt.

02300 {
02301    struct dahdi_pvt *p = pvt;
02302    p->ringt = ringt;
02303 }

static void my_set_waitingfordt ( void *  pvt,
struct ast_channel ast 
) [static]

Definition at line 2305 of file chan_dahdi.c.

References ast_log(), ast_setstate(), AST_STATE_OFFHOOK, CANPROGRESSDETECT, dahdi_pvt::dsp, LOG_DEBUG, dahdi_pvt::waitfordialtone, and dahdi_pvt::waitingfordt.

02306 {
02307    struct dahdi_pvt *p = pvt;
02308 
02309    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02310       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02311       gettimeofday(&p->waitingfordt, NULL);
02312       ast_setstate(ast, AST_STATE_OFFHOOK);
02313    }
02314 }

static int my_ss7_play_tone ( void *  pvt,
enum sig_ss7_tone  tone 
) [static]

Definition at line 3498 of file chan_dahdi.c.

References sig_ss7_tone_to_dahditone(), SUB_REAL, and dahdi_pvt::subs.

03499 {
03500    struct dahdi_pvt *p = pvt;
03501 
03502    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03503 }

static void my_ss7_set_loopback ( void *  pvt,
int  enable 
) [static]

Definition at line 3412 of file chan_dahdi.c.

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

03413 {
03414    struct dahdi_pvt *p = pvt;
03415 
03416    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03417       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03418          strerror(errno));
03419    }
03420 }

static int my_start ( void *  pvt  )  [static]

Definition at line 2942 of file chan_dahdi.c.

References SUB_REAL, and dahdi_pvt::subs.

02943 {
02944    struct dahdi_pvt *p = pvt;
02945    int x = DAHDI_START;
02946 
02947    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02948 }

static int my_start_cid_detect ( void *  pvt,
int  cid_signalling 
) [static]

Definition at line 1666 of file chan_dahdi.c.

References ast_log(), bump_gains(), callerid_new(), dahdi_pvt::cs, dahdi_setlinear(), dahdi_subchannel::dfd, LOG_ERROR, SUB_REAL, and dahdi_pvt::subs.

01667 {
01668    struct dahdi_pvt *p = pvt;
01669    int index = SUB_REAL;
01670    p->cs = callerid_new(cid_signalling);
01671    if (!p->cs) {
01672       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01673       return -1;
01674    }
01675    bump_gains(p);
01676    dahdi_setlinear(p->subs[index].dfd, 0);
01677 
01678    return 0;
01679 }

static void my_start_polarityswitch ( void *  pvt  )  [static]

Definition at line 2907 of file chan_dahdi.c.

References dahdi_pvt::answeronpolarityswitch, dahdi_pvt::hanguponpolarityswitch, and my_set_polarity().

02908 {
02909    struct dahdi_pvt *p = pvt;
02910 
02911    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02912       my_set_polarity(pvt, 0);
02913    }
02914 }

static int my_stop_callwait ( void *  pvt  )  [static]

Definition at line 1890 of file chan_dahdi.c.

References dahdi_pvt::callwaitingrepeat, dahdi_pvt::cid_suppress_expire, and dahdi_pvt::cidcwexpire.

01891 {
01892    struct dahdi_pvt *p = pvt;
01893    p->callwaitingrepeat = 0;
01894    p->cidcwexpire = 0;
01895    p->cid_suppress_expire = 0;
01896 
01897    return 0;
01898 }

static int my_stop_cid_detect ( void *  pvt  )  [static]

Definition at line 1681 of file chan_dahdi.c.

References callerid_free(), dahdi_pvt::cs, dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_subchannel::linear, SUB_REAL, and dahdi_pvt::subs.

01682 {
01683    struct dahdi_pvt *p = pvt;
01684    int index = SUB_REAL;
01685    if (p->cs)
01686       callerid_free(p->cs);
01687    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01688    return 0;
01689 }

static void my_swap_subchannels ( void *  pvt,
enum analog_sub  a,
struct ast_channel ast_a,
enum analog_sub  b,
struct ast_channel ast_b 
) [static]

Definition at line 2516 of file chan_dahdi.c.

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

02517 {
02518    struct dahdi_pvt *p = pvt;
02519    int da, db;
02520    int tchan;
02521    int tinthreeway;
02522 
02523    da = analogsub_to_dahdisub(a);
02524    db = analogsub_to_dahdisub(b);
02525 
02526    tchan = p->subs[da].chan;
02527    p->subs[da].chan = p->subs[db].chan;
02528    p->subs[db].chan = tchan;
02529 
02530    tinthreeway = p->subs[da].inthreeway;
02531    p->subs[da].inthreeway = p->subs[db].inthreeway;
02532    p->subs[db].inthreeway = tinthreeway;
02533 
02534    p->subs[da].owner = ast_a;
02535    p->subs[db].owner = ast_b;
02536 
02537    if (ast_a)
02538       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02539    if (ast_b)
02540       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02541 
02542    wakeup_sub(p, a);
02543    wakeup_sub(p, b);
02544 
02545    return;
02546 }

static int my_train_echocanceller ( void *  pvt  )  [static]

Definition at line 2983 of file chan_dahdi.c.

References dahdi_train_ec().

02984 {
02985    struct dahdi_pvt *p = pvt;
02986 
02987    dahdi_train_ec(p);
02988 
02989    return 0;
02990 }

static int my_unallocate_sub ( void *  pvt,
enum analog_sub  analogsub 
) [static]

Definition at line 2669 of file chan_dahdi.c.

References analogsub_to_dahdisub(), and unalloc_sub().

02670 {
02671    struct dahdi_pvt *p = pvt;
02672 
02673    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02674 }

static void my_unlock_private ( void *  pvt  )  [static]

Definition at line 2116 of file chan_dahdi.c.

References ast_mutex_unlock, and dahdi_pvt::lock.

02117 {
02118    struct dahdi_pvt *p = pvt;
02119    ast_mutex_unlock(&p->lock);
02120 }

static int my_wait_event ( void *  pvt  )  [static]

Definition at line 2801 of file chan_dahdi.c.

References dahdi_wait_event(), SUB_REAL, and dahdi_pvt::subs.

02802 {
02803    struct dahdi_pvt *p = pvt;
02804 
02805    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02806 }

static int my_wink ( void *  pvt,
enum analog_sub  sub 
) [static]

Definition at line 2022 of file chan_dahdi.c.

References analogsub_to_dahdisub(), ast_log(), dahdi_wink(), LOG_ERROR, and SUB_REAL.

02023 {
02024    struct dahdi_pvt *p = pvt;
02025    int index = analogsub_to_dahdisub(sub);
02026    if (index != SUB_REAL) {
02027       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02028    }
02029    return dahdi_wink(p, index);
02030 }

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

Send MWI state change.

Returns:
nothing
This function does two things:

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

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

Definition at line 3548 of file chan_dahdi.c.

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

Referenced by handle_init_event(), and my_handle_notify_message().

03549 {
03550    char s[sizeof(mwimonitornotify) + 80];
03551    struct ast_event *event;
03552    char *mailbox, *context;
03553 
03554    /* Strip off @default */
03555    context = mailbox = ast_strdupa(mailbox_full);
03556    strsep(&context, "@");
03557    if (ast_strlen_zero(context))
03558       context = "default";
03559 
03560    if (!(event = ast_event_new(AST_EVENT_MWI,
03561          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03562          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03563          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03564          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03565          AST_EVENT_IE_END))) {
03566       return;
03567    }
03568 
03569    ast_event_queue_and_cache(event);
03570 
03571    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03572       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03573       ast_safe_system(s);
03574    }
03575 }

static int parse_buffers_policy ( const char *  parse,
int *  num_buffers,
int *  policy 
) [static]

Definition at line 6975 of file chan_dahdi.c.

References ast_log(), and LOG_WARNING.

Referenced by dahdi_func_write().

06976 {
06977    int res;
06978    char policy_str[21] = "";
06979 
06980    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
06981       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
06982       return 1;
06983    }
06984    if (*num_buffers < 0) {
06985       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
06986       return -1;
06987    }
06988    if (!strcasecmp(policy_str, "full")) {
06989       *policy = DAHDI_POLICY_WHEN_FULL;
06990    } else if (!strcasecmp(policy_str, "immediate")) {
06991       *policy = DAHDI_POLICY_IMMEDIATE;
06992 #if defined(HAVE_DAHDI_HALF_FULL)
06993    } else if (!strcasecmp(policy_str, "half")) {
06994       *policy = DAHDI_POLICY_HALF_FULL;
06995 #endif
06996    } else {
06997       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
06998       return -1;
06999    }
07000 
07001    return 0;
07002 }

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

Definition at line 11988 of file chan_dahdi.c.

11989 {
11990    unsigned int code1, code2, code3;
11991    int numvals;
11992 
11993    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
11994    if (numvals == 1)
11995       return code1;
11996    if (numvals == 3)
11997       return (code1 << 16) | (code2 << 8) | code3;
11998 
11999    return 0;
12000 }

static char* parse_spanchan ( char *  chanstr,
char **  subdir 
) [static]

Definition at line 16686 of file chan_dahdi.c.

References string_replace().

Referenced by build_channels().

16687 {
16688    char *p;
16689 
16690    if ((p = strrchr(chanstr, '!')) == NULL) {
16691       *subdir = NULL;
16692       return chanstr;
16693    }
16694    *p++ = '\0';
16695    string_replace(chanstr, '!', '/');
16696    *subdir = chanstr;
16697    return p;
16698 }

static int prepare_pri ( struct dahdi_pri pri  )  [static]

Definition at line 14057 of file chan_dahdi.c.

References ast_log(), sig_pri_span::calls, dahdi_close_pri_fd(), dahdi_pri_callbacks, sig_pri_span::dchan_logical_span, dahdi_pri::dchannels, errno, sig_pri_span::fds, dahdi_pri::pri, pri_event_alarm(), pri_event_noalarm(), dahdi_pri::prilogicalspan, and pris.

Referenced by setup_dahdi_int().

14058 {
14059    int i, res, x;
14060    struct dahdi_params p;
14061    struct dahdi_bufferinfo bi;
14062    struct dahdi_spaninfo si;
14063 
14064    pri->pri.calls = &dahdi_pri_callbacks;
14065 
14066    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14067       if (!pri->dchannels[i])
14068          break;
14069       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14070       x = pri->dchannels[i];
14071       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14072          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14073          return -1;
14074       }
14075       memset(&p, 0, sizeof(p));
14076       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14077       if (res) {
14078          dahdi_close_pri_fd(pri, i);
14079          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14080          return -1;
14081       }
14082       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14083          dahdi_close_pri_fd(pri, i);
14084          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14085          return -1;
14086       }
14087       memset(&si, 0, sizeof(si));
14088       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14089       if (res) {
14090          dahdi_close_pri_fd(pri, i);
14091          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14092       }
14093       if (!si.alarms) {
14094          pri_event_noalarm(&pri->pri, i, 1);
14095       } else {
14096          pri_event_alarm(&pri->pri, i, 1);
14097       }
14098       memset(&bi, 0, sizeof(bi));
14099       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14100       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14101       bi.numbufs = 32;
14102       bi.bufsize = 1024;
14103       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14104          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14105          dahdi_close_pri_fd(pri, i);
14106          return -1;
14107       }
14108       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14109    }
14110    return 0;
14111 }

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

Definition at line 11975 of file chan_dahdi.c.

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

Referenced by setup_dahdi_int().

11976 {
11977    if (pris[span].mastertrunkgroup) {
11978       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);
11979       return -1;
11980    }
11981    pris[span].mastertrunkgroup = trunkgroup;
11982    pris[span].prilogicalspan = logicalspan;
11983    return 0;
11984 }

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

Definition at line 11912 of file chan_dahdi.c.

References ast_log(), NUM_SPANS, and pris.

Referenced by setup_dahdi_int().

11913 {
11914    struct dahdi_spaninfo si;
11915    struct dahdi_params p;
11916    int fd;
11917    int span;
11918    int ospan=0;
11919    int x,y;
11920    for (x = 0; x < NUM_SPANS; x++) {
11921       if (pris[x].pri.trunkgroup == trunkgroup) {
11922          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11923          return -1;
11924       }
11925    }
11926    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11927       if (!channels[y])
11928          break;
11929       memset(&si, 0, sizeof(si));
11930       memset(&p, 0, sizeof(p));
11931       fd = open("/dev/dahdi/channel", O_RDWR);
11932       if (fd < 0) {
11933          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11934          return -1;
11935       }
11936       x = channels[y];
11937       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11938          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11939          close(fd);
11940          return -1;
11941       }
11942       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11943          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11944          return -1;
11945       }
11946       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11947          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11948          close(fd);
11949          return -1;
11950       }
11951       span = p.spanno - 1;
11952       if (pris[span].pri.trunkgroup) {
11953          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
11954          close(fd);
11955          return -1;
11956       }
11957       if (pris[span].pri.pvts[0]) {
11958          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
11959          close(fd);
11960          return -1;
11961       }
11962       if (!y) {
11963          pris[span].pri.trunkgroup = trunkgroup;
11964          ospan = span;
11965       }
11966       pris[ospan].dchannels[y] = channels[y];
11967       pris[span].pri.span = span + 1;
11968       close(fd);
11969    }
11970    return 0;
11971 }

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

Definition at line 11866 of file chan_dahdi.c.

References ast_log(), dahdi_pri::mastertrunkgroup, NUM_SPANS, dahdi_pvt::pri, pris, and sig_pri_span::trunkgroup.

11867 {
11868    int x;
11869    int trunkgroup;
11870    /* Get appropriate trunk group if there is one */
11871    trunkgroup = pris[*span].mastertrunkgroup;
11872    if (trunkgroup) {
11873       /* Select a specific trunk group */
11874       for (x = 0; x < NUM_SPANS; x++) {
11875          if (pris[x].pri.trunkgroup == trunkgroup) {
11876             *span = x;
11877             return 0;
11878          }
11879       }
11880       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11881       *span = -1;
11882    } else {
11883       if (pris[*span].pri.trunkgroup) {
11884          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].pri.trunkgroup);
11885          *span = -1;
11886       } else if (pris[*span].mastertrunkgroup) {
11887          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11888          *span = -1;
11889       } else {
11890          if (si->totalchans == 31) {
11891             /* E1 */
11892             pris[*span].dchannels[0] = 16 + offset;
11893          } else if (si->totalchans == 24) {
11894             /* T1 or J1 */
11895             pris[*span].dchannels[0] = 24 + offset;
11896          } else if (si->totalchans == 3) {
11897             /* BRI */
11898             pris[*span].dchannels[0] = 3 + offset;
11899          } else {
11900             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);
11901             *span = -1;
11902             return 0;
11903          }
11904          pris[*span].pri.span = *span + 1;
11905       }
11906    }
11907    return 0;
11908 }

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

Definition at line 16829 of file chan_dahdi.c.

References ast_jb_read_conf(), ast_log(), build_channels(), global_jbconf, ast_variable::lineno, ast_variable::name, ast_variable::next, PROC_DAHDI_OPT_NOCHAN, and ast_variable::value.

Referenced by setup_dahdi_int().

16830 {
16831    struct dahdi_pvt *tmp;
16832    int y;
16833    int found_pseudo = 0;
16834    struct ast_variable *dahdichan = NULL;
16835 
16836    for (; v; v = v->next) {
16837       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16838          continue;
16839 
16840       /* Create the interface list */
16841       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16842          if (options & PROC_DAHDI_OPT_NOCHAN) {
16843             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16844             continue;
16845          }
16846          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16847             if (confp->ignore_failed_channels) {
16848                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16849                continue;
16850             } else {
16851                return -1;
16852             }
16853          }
16854          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16855       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16856          confp->ignore_failed_channels = ast_true(v->value);
16857       } else if (!strcasecmp(v->name, "buffers")) {
16858          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16859             ast_log(LOG_WARNING, "Using default buffer policy.\n");
16860             confp->chan.buf_no = numbufs;
16861             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16862          }
16863       } else if (!strcasecmp(v->name, "faxbuffers")) {
16864          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16865             confp->chan.usefaxbuffers = 1;
16866          }
16867       } else if (!strcasecmp(v->name, "dahdichan")) {
16868          /* Only process the last dahdichan value. */
16869          dahdichan = v;
16870       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16871          usedistinctiveringdetection = ast_true(v->value);
16872       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16873          distinctiveringaftercid = ast_true(v->value);
16874       } else if (!strcasecmp(v->name, "dring1context")) {
16875          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16876       } else if (!strcasecmp(v->name, "dring2context")) {
16877          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16878       } else if (!strcasecmp(v->name, "dring3context")) {
16879          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16880       } else if (!strcasecmp(v->name, "dring1range")) {
16881          confp->chan.drings.ringnum[0].range = atoi(v->value);
16882       } else if (!strcasecmp(v->name, "dring2range")) {
16883          confp->chan.drings.ringnum[1].range = atoi(v->value);
16884       } else if (!strcasecmp(v->name, "dring3range")) {
16885          confp->chan.drings.ringnum[2].range = atoi(v->value);
16886       } else if (!strcasecmp(v->name, "dring1")) {
16887          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]);
16888       } else if (!strcasecmp(v->name, "dring2")) {
16889          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]);
16890       } else if (!strcasecmp(v->name, "dring3")) {
16891          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]);
16892       } else if (!strcasecmp(v->name, "usecallerid")) {
16893          confp->chan.use_callerid = ast_true(v->value);
16894       } else if (!strcasecmp(v->name, "cidsignalling")) {
16895          if (!strcasecmp(v->value, "bell"))
16896             confp->chan.cid_signalling = CID_SIG_BELL;
16897          else if (!strcasecmp(v->value, "v23"))
16898             confp->chan.cid_signalling = CID_SIG_V23;
16899          else if (!strcasecmp(v->value, "dtmf"))
16900             confp->chan.cid_signalling = CID_SIG_DTMF;
16901          else if (!strcasecmp(v->value, "smdi"))
16902             confp->chan.cid_signalling = CID_SIG_SMDI;
16903          else if (!strcasecmp(v->value, "v23_jp"))
16904             confp->chan.cid_signalling = CID_SIG_V23_JP;
16905          else if (ast_true(v->value))
16906             confp->chan.cid_signalling = CID_SIG_BELL;
16907       } else if (!strcasecmp(v->name, "cidstart")) {
16908          if (!strcasecmp(v->value, "ring"))
16909             confp->chan.cid_start = CID_START_RING;
16910          else if (!strcasecmp(v->value, "polarity_in"))
16911             confp->chan.cid_start = CID_START_POLARITY_IN;
16912          else if (!strcasecmp(v->value, "polarity"))
16913             confp->chan.cid_start = CID_START_POLARITY;
16914          else if (!strcasecmp(v->value, "dtmf"))
16915             confp->chan.cid_start = CID_START_DTMF_NOALERT;
16916          else if (ast_true(v->value))
16917             confp->chan.cid_start = CID_START_RING;
16918       } else if (!strcasecmp(v->name, "threewaycalling")) {
16919          confp->chan.threewaycalling = ast_true(v->value);
16920       } else if (!strcasecmp(v->name, "cancallforward")) {
16921          confp->chan.cancallforward = ast_true(v->value);
16922       } else if (!strcasecmp(v->name, "relaxdtmf")) {
16923          if (ast_true(v->value))
16924             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16925          else
16926             confp->chan.dtmfrelax = 0;
16927       } else if (!strcasecmp(v->name, "mailbox")) {
16928          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16929       } else if (!strcasecmp(v->name, "hasvoicemail")) {
16930          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16931             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16932          }
16933       } else if (!strcasecmp(v->name, "adsi")) {
16934          confp->chan.adsi = ast_true(v->value);
16935       } else if (!strcasecmp(v->name, "usesmdi")) {
16936          confp->chan.use_smdi = ast_true(v->value);
16937       } else if (!strcasecmp(v->name, "smdiport")) {
16938          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16939       } else if (!strcasecmp(v->name, "transfer")) {
16940          confp->chan.transfer = ast_true(v->value);
16941       } else if (!strcasecmp(v->name, "canpark")) {
16942          confp->chan.canpark = ast_true(v->value);
16943       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16944          confp->chan.echocanbridged = ast_true(v->value);
16945       } else if (!strcasecmp(v->name, "busydetect")) {
16946          confp->chan.busydetect = ast_true(v->value);
16947       } else if (!strcasecmp(v->name, "busycount")) {
16948          confp->chan.busycount = atoi(v->value);
16949       } else if (!strcasecmp(v->name, "silencethreshold")) {
16950          confp->chan.silencethreshold = atoi(v->value);
16951       } else if (!strcasecmp(v->name, "busycompare")) {
16952          confp->chan.busycompare = ast_true(v->value);
16953       } else if (!strcasecmp(v->name, "busypattern")) {
16954          if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
16955             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16956          }
16957          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
16958          if (count == 1)
16959             confp->chan.busyquietlength = 0;
16960          else if (count < 1)
16961             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
16962       } else if (!strcasecmp(v->name, "busyfuzziness")) {
16963          confp->chan.busyfuzziness = atoi(v->value);
16964       } else if (!strcasecmp(v->name, "callprogress")) {
16965          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16966          if (ast_true(v->value))
16967             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16968       } else if (!strcasecmp(v->name, "waitfordialtone")) {
16969          confp->chan.waitfordialtone = atoi(v->value);
16970       } else if (!strcasecmp(v->name, "faxdetect")) {
16971          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16972          if (!strcasecmp(v->value, "incoming")) {
16973             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16974          } else if (!strcasecmp(v->value, "outgoing")) {
16975             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16976          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16977             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16978       } else if (!strcasecmp(v->name, "echocancel")) {
16979          process_echocancel(confp, v->value, v->lineno);
16980       } else if (!strcasecmp(v->name, "echotraining")) {
16981          if (sscanf(v->value, "%30d", &y) == 1) {
16982             if ((y < 10) || (y > 4000)) {
16983                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16984             } else {
16985                confp->chan.echotraining = y;
16986             }
16987          } else if (ast_true(v->value)) {
16988             confp->chan.echotraining = 400;
16989          } else
16990             confp->chan.echotraining = 0;
16991       } else if (!strcasecmp(v->name, "hidecallerid")) {
16992          confp->chan.hidecallerid = ast_true(v->value);
16993       } else if (!strcasecmp(v->name, "hidecalleridname")) {
16994          confp->chan.hidecalleridname = ast_true(v->value);
16995       } else if (!strcasecmp(v->name, "pulsedial")) {
16996          confp->chan.pulse = ast_true(v->value);
16997       } else if (!strcasecmp(v->name, "callreturn")) {
16998          confp->chan.callreturn = ast_true(v->value);
16999       } else if (!strcasecmp(v->name, "callwaiting")) {
17000          confp->chan.callwaiting = ast_true(v->value);
17001       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17002          confp->chan.callwaitingcallerid = ast_true(v->value);
17003       } else if (!strcasecmp(v->name, "context")) {
17004          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17005       } else if (!strcasecmp(v->name, "language")) {
17006          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17007       } else if (!strcasecmp(v->name, "progzone")) {
17008          ast_copy_string(progzone, v->value, sizeof(progzone));
17009       } else if (!strcasecmp(v->name, "mohinterpret")
17010          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17011          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17012       } else if (!strcasecmp(v->name, "mohsuggest")) {
17013          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17014       } else if (!strcasecmp(v->name, "parkinglot")) {
17015          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17016       } else if (!strcasecmp(v->name, "stripmsd")) {
17017          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17018          confp->chan.stripmsd = atoi(v->value);
17019       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17020          numbufs = atoi(v->value);
17021       } else if (!strcasecmp(v->name, "group")) {
17022          confp->chan.group = ast_get_group(v->value);
17023       } else if (!strcasecmp(v->name, "callgroup")) {
17024          if (!strcasecmp(v->value, "none"))
17025             confp->chan.callgroup = 0;
17026          else
17027             confp->chan.callgroup = ast_get_group(v->value);
17028       } else if (!strcasecmp(v->name, "pickupgroup")) {
17029          if (!strcasecmp(v->value, "none"))
17030             confp->chan.pickupgroup = 0;
17031          else
17032             confp->chan.pickupgroup = ast_get_group(v->value);
17033       } else if (!strcasecmp(v->name, "setvar")) {
17034          char *varname = ast_strdupa(v->value), *varval = NULL;
17035          struct ast_variable *tmpvar;
17036          if (varname && (varval = strchr(varname, '='))) {
17037             *varval++ = '\0';
17038             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17039                tmpvar->next = confp->chan.vars;
17040                confp->chan.vars = tmpvar;
17041             }
17042          }
17043       } else if (!strcasecmp(v->name, "immediate")) {
17044          confp->chan.immediate = ast_true(v->value);
17045       } else if (!strcasecmp(v->name, "transfertobusy")) {
17046          confp->chan.transfertobusy = ast_true(v->value);
17047       } else if (!strcasecmp(v->name, "mwimonitor")) {
17048          confp->chan.mwimonitor_neon = 0;
17049          confp->chan.mwimonitor_fsk = 0;
17050          confp->chan.mwimonitor_rpas = 0;
17051          if (strcasestr(v->value, "fsk")) {
17052             confp->chan.mwimonitor_fsk = 1;
17053          }
17054          if (strcasestr(v->value, "rpas")) {
17055             confp->chan.mwimonitor_rpas = 1;
17056          }
17057          if (strcasestr(v->value, "neon")) {
17058             confp->chan.mwimonitor_neon = 1;
17059          }
17060          /* If set to true or yes, assume that simple fsk is desired */
17061          if (ast_true(v->value)) {
17062             confp->chan.mwimonitor_fsk = 1;
17063          }
17064       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17065          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17066             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17067          }
17068       } else if (!strcasecmp(v->name, "rxgain")) {
17069          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17070             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17071          }
17072       } else if (!strcasecmp(v->name, "txgain")) {
17073          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17074             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17075          }
17076       } else if (!strcasecmp(v->name, "txdrc")) {
17077          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17078             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17079          }
17080       } else if (!strcasecmp(v->name, "rxdrc")) {
17081          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17082             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17083          }
17084       } else if (!strcasecmp(v->name, "tonezone")) {
17085          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17086             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17087          }
17088       } else if (!strcasecmp(v->name, "callerid")) {
17089          if (!strcasecmp(v->value, "asreceived")) {
17090             confp->chan.cid_num[0] = '\0';
17091             confp->chan.cid_name[0] = '\0';
17092          } else {
17093             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17094          }
17095       } else if (!strcasecmp(v->name, "fullname")) {
17096          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17097       } else if (!strcasecmp(v->name, "cid_number")) {
17098          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17099       } else if (!strcasecmp(v->name, "cid_tag")) {
17100          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17101       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17102          confp->chan.dahditrcallerid = ast_true(v->value);
17103       } else if (!strcasecmp(v->name, "restrictcid")) {
17104          confp->chan.restrictcid = ast_true(v->value);
17105       } else if (!strcasecmp(v->name, "usecallingpres")) {
17106          confp->chan.use_callingpres = ast_true(v->value);
17107       } else if (!strcasecmp(v->name, "accountcode")) {
17108          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17109       } else if (!strcasecmp(v->name, "amaflags")) {
17110          y = ast_cdr_amaflags2int(v->value);
17111          if (y < 0)
17112             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17113          else
17114             confp->chan.amaflags = y;
17115       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17116          confp->chan.polarityonanswerdelay = atoi(v->value);
17117       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17118          confp->chan.answeronpolarityswitch = ast_true(v->value);
17119       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17120          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17121       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17122          confp->chan.sendcalleridafter = atoi(v->value);
17123       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17124          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17125       } else if (ast_cc_is_config_param(v->name)) {
17126          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17127       } else if (!strcasecmp(v->name, "mwisendtype")) {
17128 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17129          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17130             mwisend_rpas = 1;
17131          } else {
17132             mwisend_rpas = 0;
17133          }
17134 #else
17135          /* Default is fsk, to turn it off you must specify nofsk */
17136          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17137          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17138             confp->chan.mwisend_fsk = 0;
17139          } else {             /* Default FSK */
17140             confp->chan.mwisend_fsk = 1;
17141          }
17142          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17143             confp->chan.mwisend_rpas = 1;
17144          } else {
17145             confp->chan.mwisend_rpas = 0;
17146          }
17147          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17148             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17149          }
17150          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17151             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17152          }
17153          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17154             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17155          }
17156 #endif
17157       } else if (reload != 1) {
17158           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17159             int orig_radio = confp->chan.radio;
17160             int orig_outsigmod = confp->chan.outsigmod;
17161             int orig_auto = confp->is_sig_auto;
17162 
17163             confp->chan.radio = 0;
17164             confp->chan.outsigmod = -1;
17165             confp->is_sig_auto = 0;
17166             if (!strcasecmp(v->value, "em")) {
17167                confp->chan.sig = SIG_EM;
17168             } else if (!strcasecmp(v->value, "em_e1")) {
17169                confp->chan.sig = SIG_EM_E1;
17170             } else if (!strcasecmp(v->value, "em_w")) {
17171                confp->chan.sig = SIG_EMWINK;
17172             } else if (!strcasecmp(v->value, "fxs_ls")) {
17173                confp->chan.sig = SIG_FXSLS;
17174             } else if (!strcasecmp(v->value, "fxs_gs")) {
17175                confp->chan.sig = SIG_FXSGS;
17176             } else if (!strcasecmp(v->value, "fxs_ks")) {
17177                confp->chan.sig = SIG_FXSKS;
17178             } else if (!strcasecmp(v->value, "fxo_ls")) {
17179                confp->chan.sig = SIG_FXOLS;
17180             } else if (!strcasecmp(v->value, "fxo_gs")) {
17181                confp->chan.sig = SIG_FXOGS;
17182             } else if (!strcasecmp(v->value, "fxo_ks")) {
17183                confp->chan.sig = SIG_FXOKS;
17184             } else if (!strcasecmp(v->value, "fxs_rx")) {
17185                confp->chan.sig = SIG_FXSKS;
17186                confp->chan.radio = 1;
17187             } else if (!strcasecmp(v->value, "fxo_rx")) {
17188                confp->chan.sig = SIG_FXOLS;
17189                confp->chan.radio = 1;
17190             } else if (!strcasecmp(v->value, "fxs_tx")) {
17191                confp->chan.sig = SIG_FXSLS;
17192                confp->chan.radio = 1;
17193             } else if (!strcasecmp(v->value, "fxo_tx")) {
17194                confp->chan.sig = SIG_FXOGS;
17195                confp->chan.radio = 1;
17196             } else if (!strcasecmp(v->value, "em_rx")) {
17197                confp->chan.sig = SIG_EM;
17198                confp->chan.radio = 1;
17199             } else if (!strcasecmp(v->value, "em_tx")) {
17200                confp->chan.sig = SIG_EM;
17201                confp->chan.radio = 1;
17202             } else if (!strcasecmp(v->value, "em_rxtx")) {
17203                confp->chan.sig = SIG_EM;
17204                confp->chan.radio = 2;
17205             } else if (!strcasecmp(v->value, "em_txrx")) {
17206                confp->chan.sig = SIG_EM;
17207                confp->chan.radio = 2;
17208             } else if (!strcasecmp(v->value, "sf")) {
17209                confp->chan.sig = SIG_SF;
17210             } else if (!strcasecmp(v->value, "sf_w")) {
17211                confp->chan.sig = SIG_SFWINK;
17212             } else if (!strcasecmp(v->value, "sf_featd")) {
17213                confp->chan.sig = SIG_FEATD;
17214             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17215                confp->chan.sig = SIG_FEATDMF;
17216             } else if (!strcasecmp(v->value, "sf_featb")) {
17217                confp->chan.sig = SIG_SF_FEATB;
17218             } else if (!strcasecmp(v->value, "sf")) {
17219                confp->chan.sig = SIG_SF;
17220             } else if (!strcasecmp(v->value, "sf_rx")) {
17221                confp->chan.sig = SIG_SF;
17222                confp->chan.radio = 1;
17223             } else if (!strcasecmp(v->value, "sf_tx")) {
17224                confp->chan.sig = SIG_SF;
17225                confp->chan.radio = 1;
17226             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17227                confp->chan.sig = SIG_SF;
17228                confp->chan.radio = 2;
17229             } else if (!strcasecmp(v->value, "sf_txrx")) {
17230                confp->chan.sig = SIG_SF;
17231                confp->chan.radio = 2;
17232             } else if (!strcasecmp(v->value, "featd")) {
17233                confp->chan.sig = SIG_FEATD;
17234             } else if (!strcasecmp(v->value, "featdmf")) {
17235                confp->chan.sig = SIG_FEATDMF;
17236             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17237                confp->chan.sig = SIG_FEATDMF_TA;
17238             } else if (!strcasecmp(v->value, "e911")) {
17239                confp->chan.sig = SIG_E911;
17240             } else if (!strcasecmp(v->value, "fgccama")) {
17241                confp->chan.sig = SIG_FGC_CAMA;
17242             } else if (!strcasecmp(v->value, "fgccamamf")) {
17243                confp->chan.sig = SIG_FGC_CAMAMF;
17244             } else if (!strcasecmp(v->value, "featb")) {
17245                confp->chan.sig = SIG_FEATB;
17246 #ifdef HAVE_PRI
17247             } else if (!strcasecmp(v->value, "pri_net")) {
17248                confp->chan.sig = SIG_PRI;
17249                confp->pri.pri.nodetype = PRI_NETWORK;
17250             } else if (!strcasecmp(v->value, "pri_cpe")) {
17251                confp->chan.sig = SIG_PRI;
17252                confp->pri.pri.nodetype = PRI_CPE;
17253             } else if (!strcasecmp(v->value, "bri_cpe")) {
17254                confp->chan.sig = SIG_BRI;
17255                confp->pri.pri.nodetype = PRI_CPE;
17256             } else if (!strcasecmp(v->value, "bri_net")) {
17257                confp->chan.sig = SIG_BRI;
17258                confp->pri.pri.nodetype = PRI_NETWORK;
17259             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17260                confp->chan.sig = SIG_BRI_PTMP;
17261                confp->pri.pri.nodetype = PRI_CPE;
17262             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17263 #if defined(HAVE_PRI_CALL_HOLD)
17264                confp->chan.sig = SIG_BRI_PTMP;
17265                confp->pri.pri.nodetype = PRI_NETWORK;
17266 #else
17267                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17268 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
17269 #endif
17270 #if defined(HAVE_SS7)
17271             } else if (!strcasecmp(v->value, "ss7")) {
17272                confp->chan.sig = SIG_SS7;
17273 #endif   /* defined(HAVE_SS7) */
17274 #ifdef HAVE_OPENR2
17275             } else if (!strcasecmp(v->value, "mfcr2")) {
17276                confp->chan.sig = SIG_MFCR2;
17277 #endif
17278             } else if (!strcasecmp(v->value, "auto")) {
17279                confp->is_sig_auto = 1;
17280             } else {
17281                confp->chan.outsigmod = orig_outsigmod;
17282                confp->chan.radio = orig_radio;
17283                confp->is_sig_auto = orig_auto;
17284                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17285             }
17286           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17287             if (!strcasecmp(v->value, "em")) {
17288                confp->chan.outsigmod = SIG_EM;
17289             } else if (!strcasecmp(v->value, "em_e1")) {
17290                confp->chan.outsigmod = SIG_EM_E1;
17291             } else if (!strcasecmp(v->value, "em_w")) {
17292                confp->chan.outsigmod = SIG_EMWINK;
17293             } else if (!strcasecmp(v->value, "sf")) {
17294                confp->chan.outsigmod = SIG_SF;
17295             } else if (!strcasecmp(v->value, "sf_w")) {
17296                confp->chan.outsigmod = SIG_SFWINK;
17297             } else if (!strcasecmp(v->value, "sf_featd")) {
17298                confp->chan.outsigmod = SIG_FEATD;
17299             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17300                confp->chan.outsigmod = SIG_FEATDMF;
17301             } else if (!strcasecmp(v->value, "sf_featb")) {
17302                confp->chan.outsigmod = SIG_SF_FEATB;
17303             } else if (!strcasecmp(v->value, "sf")) {
17304                confp->chan.outsigmod = SIG_SF;
17305             } else if (!strcasecmp(v->value, "featd")) {
17306                confp->chan.outsigmod = SIG_FEATD;
17307             } else if (!strcasecmp(v->value, "featdmf")) {
17308                confp->chan.outsigmod = SIG_FEATDMF;
17309             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17310                confp->chan.outsigmod = SIG_FEATDMF_TA;
17311             } else if (!strcasecmp(v->value, "e911")) {
17312                confp->chan.outsigmod = SIG_E911;
17313             } else if (!strcasecmp(v->value, "fgccama")) {
17314                confp->chan.outsigmod = SIG_FGC_CAMA;
17315             } else if (!strcasecmp(v->value, "fgccamamf")) {
17316                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17317             } else if (!strcasecmp(v->value, "featb")) {
17318                confp->chan.outsigmod = SIG_FEATB;
17319             } else {
17320                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17321             }
17322 #ifdef HAVE_PRI
17323          } else if (!strcasecmp(v->name, "pridialplan")) {
17324             if (!strcasecmp(v->value, "national")) {
17325                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17326             } else if (!strcasecmp(v->value, "unknown")) {
17327                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17328             } else if (!strcasecmp(v->value, "private")) {
17329                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17330             } else if (!strcasecmp(v->value, "international")) {
17331                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17332             } else if (!strcasecmp(v->value, "local")) {
17333                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17334             } else if (!strcasecmp(v->value, "dynamic")) {
17335                confp->pri.pri.dialplan = -1;
17336             } else if (!strcasecmp(v->value, "redundant")) {
17337                confp->pri.pri.dialplan = -2;
17338             } else {
17339                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17340             }
17341          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17342             if (!strcasecmp(v->value, "national")) {
17343                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17344             } else if (!strcasecmp(v->value, "unknown")) {
17345                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17346             } else if (!strcasecmp(v->value, "private")) {
17347                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17348             } else if (!strcasecmp(v->value, "international")) {
17349                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17350             } else if (!strcasecmp(v->value, "local")) {
17351                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17352             } else if (!strcasecmp(v->value, "dynamic")) {
17353                confp->pri.pri.localdialplan = -1;
17354             } else if (!strcasecmp(v->value, "redundant")) {
17355                confp->pri.pri.localdialplan = -2;
17356             } else {
17357                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17358             }
17359          } else if (!strcasecmp(v->name, "switchtype")) {
17360             if (!strcasecmp(v->value, "national"))
17361                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17362             else if (!strcasecmp(v->value, "ni1"))
17363                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17364             else if (!strcasecmp(v->value, "dms100"))
17365                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17366             else if (!strcasecmp(v->value, "4ess"))
17367                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17368             else if (!strcasecmp(v->value, "5ess"))
17369                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17370             else if (!strcasecmp(v->value, "euroisdn"))
17371                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17372             else if (!strcasecmp(v->value, "qsig"))
17373                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17374             else {
17375                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17376                return -1;
17377             }
17378          } else if (!strcasecmp(v->name, "msn")) {
17379             ast_copy_string(confp->pri.pri.msn_list, v->value,
17380                sizeof(confp->pri.pri.msn_list));
17381          } else if (!strcasecmp(v->name, "nsf")) {
17382             if (!strcasecmp(v->value, "sdn"))
17383                confp->pri.pri.nsf = PRI_NSF_SDN;
17384             else if (!strcasecmp(v->value, "megacom"))
17385                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17386             else if (!strcasecmp(v->value, "tollfreemegacom"))
17387                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17388             else if (!strcasecmp(v->value, "accunet"))
17389                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17390             else if (!strcasecmp(v->value, "none"))
17391                confp->pri.pri.nsf = PRI_NSF_NONE;
17392             else {
17393                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17394                confp->pri.pri.nsf = PRI_NSF_NONE;
17395             }
17396          } else if (!strcasecmp(v->name, "priindication")) {
17397             if (!strcasecmp(v->value, "outofband"))
17398                confp->chan.priindication_oob = 1;
17399             else if (!strcasecmp(v->value, "inband"))
17400                confp->chan.priindication_oob = 0;
17401             else
17402                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17403                   v->value, v->lineno);
17404          } else if (!strcasecmp(v->name, "priexclusive")) {
17405             confp->chan.priexclusive = ast_true(v->value);
17406          } else if (!strcasecmp(v->name, "internationalprefix")) {
17407             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17408          } else if (!strcasecmp(v->name, "nationalprefix")) {
17409             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17410          } else if (!strcasecmp(v->name, "localprefix")) {
17411             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17412          } else if (!strcasecmp(v->name, "privateprefix")) {
17413             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17414          } else if (!strcasecmp(v->name, "unknownprefix")) {
17415             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17416          } else if (!strcasecmp(v->name, "resetinterval")) {
17417             if (!strcasecmp(v->value, "never"))
17418                confp->pri.pri.resetinterval = -1;
17419             else if (atoi(v->value) >= 60)
17420                confp->pri.pri.resetinterval = atoi(v->value);
17421             else
17422                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17423                   v->value, v->lineno);
17424          } else if (!strcasecmp(v->name, "minunused")) {
17425             confp->pri.pri.minunused = atoi(v->value);
17426          } else if (!strcasecmp(v->name, "minidle")) {
17427             confp->pri.pri.minidle = atoi(v->value);
17428          } else if (!strcasecmp(v->name, "idleext")) {
17429             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17430          } else if (!strcasecmp(v->name, "idledial")) {
17431             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17432          } else if (!strcasecmp(v->name, "overlapdial")) {
17433             if (ast_true(v->value)) {
17434                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17435             } else if (!strcasecmp(v->value, "incoming")) {
17436                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17437             } else if (!strcasecmp(v->value, "outgoing")) {
17438                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17439             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17440                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17441             } else {
17442                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17443             }
17444 #ifdef HAVE_PRI_PROG_W_CAUSE
17445          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17446             if (!strcasecmp(v->value, "logical")) {
17447                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17448             } else if (!strcasecmp(v->value, "physical")) {
17449                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17450             } else {
17451                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17452             }
17453 #endif
17454          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17455             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17456 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17457          } else if (!strcasecmp(v->name, "service_message_support")) {
17458             /* assuming switchtype for this channel group has been configured already */
17459             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17460                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17461                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17462                confp->pri.pri.enable_service_message_support = 1;
17463             } else {
17464                confp->pri.pri.enable_service_message_support = 0;
17465             }
17466 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17467 #ifdef HAVE_PRI_INBANDDISCONNECT
17468          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17469             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17470 #endif
17471          } else if (!strcasecmp(v->name, "pritimer")) {
17472 #ifdef PRI_GETSET_TIMERS
17473             char tmp[20];
17474             char *timerc;
17475             char *c;
17476             int timer;
17477             int timeridx;
17478 
17479             ast_copy_string(tmp, v->value, sizeof(tmp));
17480             c = tmp;
17481             timerc = strsep(&c, ",");
17482             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17483                timeridx = pri_timer2idx(timerc);
17484                timer = atoi(c);
17485                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17486                   ast_log(LOG_WARNING,
17487                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17488                      v->lineno);
17489                } else if (!timer) {
17490                   ast_log(LOG_WARNING,
17491                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17492                      c, timerc, v->lineno);
17493                } else {
17494                   confp->pri.pri.pritimers[timeridx] = timer;
17495                }
17496             } else {
17497                ast_log(LOG_WARNING,
17498                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17499                   v->value, v->lineno);
17500             }
17501 #endif /* PRI_GETSET_TIMERS */
17502          } else if (!strcasecmp(v->name, "facilityenable")) {
17503             confp->pri.pri.facilityenable = ast_true(v->value);
17504 #if defined(HAVE_PRI_AOC_EVENTS)
17505          } else if (!strcasecmp(v->name, "aoc_enable")) {
17506             confp->pri.pri.aoc_passthrough_flag = 0;
17507             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17508                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17509             }
17510             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17511                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17512             }
17513             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17514                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17515             }
17516          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17517             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17518 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17519 #if defined(HAVE_PRI_CALL_HOLD)
17520          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17521             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17522 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17523 #if defined(HAVE_PRI_CCSS)
17524          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17525             if (!strcasecmp(v->value, "global")) {
17526                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17527             } else if (!strcasecmp(v->value, "specific")) {
17528                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17529             } else {
17530                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17531             }
17532          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17533             if (!strcasecmp(v->value, "release")) {
17534                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17535             } else if (!strcasecmp(v->value, "retain")) {
17536                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17537             } else if (!strcasecmp(v->value, "do_not_care")) {
17538                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17539             } else {
17540                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17541             }
17542          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17543             if (!strcasecmp(v->value, "release")) {
17544                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17545             } else if (!strcasecmp(v->value, "retain")) {
17546                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17547             } else {
17548                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17549             }
17550 #endif   /* defined(HAVE_PRI_CCSS) */
17551 #if defined(HAVE_PRI_CALL_WAITING)
17552          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17553             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17554             if (confp->pri.pri.max_call_waiting_calls < 0) {
17555                /* Negative values are not allowed. */
17556                confp->pri.pri.max_call_waiting_calls = 0;
17557             }
17558          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17559             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17560 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17561 #if defined(HAVE_PRI_MWI)
17562          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17563             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17564                sizeof(confp->pri.pri.mwi_mailboxes));
17565 #endif   /* defined(HAVE_PRI_MWI) */
17566          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17567             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17568 #if defined(HAVE_PRI_L2_PERSISTENCE)
17569          } else if (!strcasecmp(v->name, "layer2_persistence")) {
17570             if (!strcasecmp(v->value, "keep_up")) {
17571                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17572             } else if (!strcasecmp(v->value, "leave_down")) {
17573                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17574             } else {
17575                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17576             }
17577 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
17578 #endif /* HAVE_PRI */
17579 #if defined(HAVE_SS7)
17580          } else if (!strcasecmp(v->name, "ss7type")) {
17581             if (!strcasecmp(v->value, "itu")) {
17582                cur_ss7type = SS7_ITU;
17583             } else if (!strcasecmp(v->value, "ansi")) {
17584                cur_ss7type = SS7_ANSI;
17585             } else
17586                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17587          } else if (!strcasecmp(v->name, "linkset")) {
17588             cur_linkset = atoi(v->value);
17589          } else if (!strcasecmp(v->name, "pointcode")) {
17590             cur_pointcode = parse_pointcode(v->value);
17591          } else if (!strcasecmp(v->name, "adjpointcode")) {
17592             cur_adjpointcode = parse_pointcode(v->value);
17593          } else if (!strcasecmp(v->name, "defaultdpc")) {
17594             cur_defaultdpc = parse_pointcode(v->value);
17595          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17596             cur_cicbeginswith = atoi(v->value);
17597          } else if (!strcasecmp(v->name, "networkindicator")) {
17598             if (!strcasecmp(v->value, "national"))
17599                cur_networkindicator = SS7_NI_NAT;
17600             else if (!strcasecmp(v->value, "national_spare"))
17601                cur_networkindicator = SS7_NI_NAT_SPARE;
17602             else if (!strcasecmp(v->value, "international"))
17603                cur_networkindicator = SS7_NI_INT;
17604             else if (!strcasecmp(v->value, "international_spare"))
17605                cur_networkindicator = SS7_NI_INT_SPARE;
17606             else
17607                cur_networkindicator = -1;
17608          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17609             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17610          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17611             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17612          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17613             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17614          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17615             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17616          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17617             if (!strcasecmp(v->value, "national")) {
17618                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17619             } else if (!strcasecmp(v->value, "international")) {
17620                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17621             } else if (!strcasecmp(v->value, "subscriber")) {
17622                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17623             } else if (!strcasecmp(v->value, "unknown")) {
17624                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17625             } else if (!strcasecmp(v->value, "dynamic")) {
17626                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17627             } else {
17628                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17629             }
17630          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17631             if (!strcasecmp(v->value, "national")) {
17632                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17633             } else if (!strcasecmp(v->value, "international")) {
17634                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17635             } else if (!strcasecmp(v->value, "subscriber")) {
17636                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17637             } else if (!strcasecmp(v->value, "unknown")) {
17638                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17639             } else if (!strcasecmp(v->value, "dynamic")) {
17640                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17641             } else {
17642                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17643             }
17644          } else if (!strcasecmp(v->name, "sigchan")) {
17645             int sigchan, res;
17646             sigchan = atoi(v->value);
17647             res = linkset_addsigchan(sigchan);
17648             if (res < 0)
17649                return -1;
17650 
17651          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17652             struct dahdi_ss7 *link;
17653             link = ss7_resolve_linkset(cur_linkset);
17654             if (!link) {
17655                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17656                return -1;
17657             }
17658             if (ast_true(v->value))
17659                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17660 #endif   /* defined(HAVE_SS7) */
17661 #ifdef HAVE_OPENR2
17662          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17663             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17664             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);
17665          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17666             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17667          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17668             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17669             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17670                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17671                confp->mfcr2.variant = OR2_VAR_ITU;
17672             }
17673          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17674             confp->mfcr2.mfback_timeout = atoi(v->value);
17675             if (!confp->mfcr2.mfback_timeout) {
17676                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17677                confp->mfcr2.mfback_timeout = -1;
17678             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17679                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17680             }
17681          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17682             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17683             if (confp->mfcr2.metering_pulse_timeout > 500) {
17684                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17685             }
17686          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17687             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17688          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17689             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17690          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17691             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17692          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17693             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17694          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17695             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17696          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17697             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17698          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17699             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17700 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17701          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17702             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17703 #endif
17704          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17705             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17706          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17707             confp->mfcr2.max_ani = atoi(v->value);
17708             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17709                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17710             }
17711          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17712             confp->mfcr2.max_dnis = atoi(v->value);
17713             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17714                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17715             }
17716          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17717             confp->mfcr2.category = openr2_proto_get_category(v->value);
17718             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17719                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17720                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17721                      v->value, v->lineno);
17722             }
17723          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17724             openr2_log_level_t tmplevel;
17725             char *clevel;
17726             char *logval = ast_strdupa(v->value);
17727             while (logval) {
17728                clevel = strsep(&logval,",");
17729                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17730                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17731                   continue;
17732                }
17733                confp->mfcr2.loglevel |= tmplevel;
17734             }
17735 #endif /* HAVE_OPENR2 */
17736          } else if (!strcasecmp(v->name, "cadence")) {
17737             /* setup to scan our argument */
17738             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17739             int i;
17740             struct dahdi_ring_cadence new_cadence;
17741             int cid_location = -1;
17742             int firstcadencepos = 0;
17743             char original_args[80];
17744             int cadence_is_ok = 1;
17745 
17746             ast_copy_string(original_args, v->value, sizeof(original_args));
17747             /* 16 cadences allowed (8 pairs) */
17748             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]);
17749 
17750             /* Cadence must be even (on/off) */
17751             if (element_count % 2 == 1) {
17752                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17753                cadence_is_ok = 0;
17754             }
17755 
17756             /* Ring cadences cannot be negative */
17757             for (i = 0; i < element_count; i++) {
17758                if (c[i] == 0) {
17759                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17760                   cadence_is_ok = 0;
17761                   break;
17762                } else if (c[i] < 0) {
17763                   if (i % 2 == 1) {
17764                      /* Silence duration, negative possibly okay */
17765                      if (cid_location == -1) {
17766                         cid_location = i;
17767                         c[i] *= -1;
17768                      } else {
17769                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17770                         cadence_is_ok = 0;
17771                         break;
17772                      }
17773                   } else {
17774                      if (firstcadencepos == 0) {
17775                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17776                                  /* duration will be passed negative to the DAHDI driver */
17777                      } else {
17778                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17779                         cadence_is_ok = 0;
17780                         break;
17781                      }
17782                   }
17783                }
17784             }
17785 
17786             /* Substitute our scanned cadence */
17787             for (i = 0; i < 16; i++) {
17788                new_cadence.ringcadence[i] = c[i];
17789             }
17790 
17791             if (cadence_is_ok) {
17792                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17793                if (element_count < 2) {
17794                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17795                } else {
17796                   if (cid_location == -1) {
17797                      /* user didn't say; default to first pause */
17798                      cid_location = 1;
17799                   } else {
17800                      /* convert element_index to cidrings value */
17801                      cid_location = (cid_location + 1) / 2;
17802                   }
17803                   /* ---we like their cadence; try to install it--- */
17804                   if (!user_has_defined_cadences++)
17805                      /* this is the first user-defined cadence; clear the default user cadences */
17806                      num_cadence = 0;
17807                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17808                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17809                   else {
17810                      cadences[num_cadence] = new_cadence;
17811                      cidrings[num_cadence++] = cid_location;
17812                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17813                   }
17814                }
17815             }
17816          } else if (!strcasecmp(v->name, "ringtimeout")) {
17817             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17818          } else if (!strcasecmp(v->name, "prewink")) {
17819             confp->timing.prewinktime = atoi(v->value);
17820          } else if (!strcasecmp(v->name, "preflash")) {
17821             confp->timing.preflashtime = atoi(v->value);
17822          } else if (!strcasecmp(v->name, "wink")) {
17823             confp->timing.winktime = atoi(v->value);
17824          } else if (!strcasecmp(v->name, "flash")) {
17825             confp->timing.flashtime = atoi(v->value);
17826          } else if (!strcasecmp(v->name, "start")) {
17827             confp->timing.starttime = atoi(v->value);
17828          } else if (!strcasecmp(v->name, "rxwink")) {
17829             confp->timing.rxwinktime = atoi(v->value);
17830          } else if (!strcasecmp(v->name, "rxflash")) {
17831             confp->timing.rxflashtime = atoi(v->value);
17832          } else if (!strcasecmp(v->name, "debounce")) {
17833             confp->timing.debouncetime = atoi(v->value);
17834          } else if (!strcasecmp(v->name, "toneduration")) {
17835             int toneduration;
17836             int ctlfd;
17837             int res;
17838             struct dahdi_dialparams dps;
17839 
17840             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17841             if (ctlfd == -1) {
17842                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17843                return -1;
17844             }
17845 
17846             toneduration = atoi(v->value);
17847             if (toneduration > -1) {
17848                memset(&dps, 0, sizeof(dps));
17849 
17850                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17851                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17852                if (res < 0) {
17853                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17854                   close(ctlfd);
17855                   return -1;
17856                }
17857             }
17858             close(ctlfd);
17859          } else if (!strcasecmp(v->name, "defaultcic")) {
17860             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17861          } else if (!strcasecmp(v->name, "defaultozz")) {
17862             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17863          } else if (!strcasecmp(v->name, "mwilevel")) {
17864             mwilevel = atoi(v->value);
17865          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17866             dtmfcid_level = atoi(v->value);
17867          } else if (!strcasecmp(v->name, "reportalarms")) {
17868             if (!strcasecmp(v->value, "all"))
17869                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17870             if (!strcasecmp(v->value, "none"))
17871                report_alarms = 0;
17872             else if (!strcasecmp(v->value, "channels"))
17873                report_alarms = REPORT_CHANNEL_ALARMS;
17874             else if (!strcasecmp(v->value, "spans"))
17875                report_alarms = REPORT_SPAN_ALARMS;
17876           }
17877       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17878          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17879    }
17880 
17881    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
17882    if (confp->chan.vars) {
17883       ast_variables_destroy(confp->chan.vars);
17884       confp->chan.vars = NULL;
17885    }
17886 
17887    if (dahdichan) {
17888       /* Process the deferred dahdichan value. */
17889       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
17890          &found_pseudo)) {
17891          if (confp->ignore_failed_channels) {
17892             ast_log(LOG_WARNING,
17893                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
17894                dahdichan->value);
17895          } else {
17896             return -1;
17897          }
17898       }
17899    }
17900 
17901    /* mark the first channels of each DAHDI span to watch for their span alarms */
17902    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17903       if (!tmp->destroy && tmp->span != y) {
17904          tmp->manages_span_alarms = 1;
17905          y = tmp->span; 
17906       } else {
17907          tmp->manages_span_alarms = 0;
17908       }
17909    }
17910 
17911    /*< \todo why check for the pseudo in the per-channel section.
17912     * Any actual use for manual setup of the pseudo channel? */
17913    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
17914       /* use the default configuration for a channel, so
17915          that any settings from real configured channels
17916          don't "leak" into the pseudo channel config
17917       */
17918       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17919 
17920       if (conf.chan.cc_params) {
17921          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
17922       } else {
17923          tmp = NULL;
17924       }
17925       if (tmp) {
17926          ast_verb(3, "Automatically generated pseudo channel\n");
17927       } else {
17928          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17929       }
17930       ast_cc_config_params_destroy(conf.chan.cc_params);
17931    }
17932    return 0;
17933 }

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

Definition at line 16773 of file chan_dahdi.c.

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

16774 {
16775    char *parse = ast_strdupa(data);
16776    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16777    unsigned int param_count;
16778    unsigned int x;
16779 
16780    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16781       return;
16782 
16783    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16784 
16785    /* first parameter is tap length, process it here */
16786 
16787    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16788 
16789    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16790       confp->chan.echocancel.head.tap_length = x;
16791    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16792       confp->chan.echocancel.head.tap_length = 128;
16793 
16794    /* now process any remaining parameters */
16795 
16796    for (x = 1; x < param_count; x++) {
16797       struct {
16798          char *name;
16799          char *value;
16800       } param;
16801 
16802       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16803          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16804          continue;
16805       }
16806 
16807       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16808          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16809          continue;
16810       }
16811 
16812       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16813 
16814       if (param.value) {
16815          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16816             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16817             continue;
16818          }
16819       }
16820       confp->chan.echocancel.head.param_count++;
16821    }
16822 }

static int reload ( void   )  [static]

Definition at line 18611 of file chan_dahdi.c.

References ast_log(), and setup_dahdi().

18612 {
18613    int res = 0;
18614 
18615    res = setup_dahdi(1);
18616    if (res) {
18617       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18618       return -1;
18619    }
18620    return 0;
18621 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

Definition at line 4763 of file chan_dahdi.c.

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

Referenced by dahdi_hangup(), and my_all_subchannels_hungup().

04764 {
04765    p->confno = -1;
04766    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04767    if (p->subs[SUB_REAL].dfd > -1) {
04768       struct dahdi_confinfo zi;
04769 
04770       memset(&zi, 0, sizeof(zi));
04771       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04772          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04773    }
04774    return 0;
04775 }

static int restart_monitor ( void   )  [static]

Definition at line 11839 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, monitor_thread, and monlock.

Referenced by dahdi_hangup(), dahdi_request(), h323_reload(), load_module(), mgcp_reload(), mgcp_request(), my_all_subchannels_hungup(), oh323_request(), phone_hangup(), phone_request(), sip_reload(), sip_request_call(), skinny_request(), unistim_reload(), and unistim_request().

11840 {
11841    /* If we're supposed to be stopped -- stay stopped */
11842    if (monitor_thread == AST_PTHREADT_STOP)
11843       return 0;
11844    ast_mutex_lock(&monlock);
11845    if (monitor_thread == pthread_self()) {
11846       ast_mutex_unlock(&monlock);
11847       ast_log(LOG_WARNING, "Cannot kill myself\n");
11848       return -1;
11849    }
11850    if (monitor_thread != AST_PTHREADT_NULL) {
11851       /* Wake up the thread */
11852       pthread_kill(monitor_thread, SIGURG);
11853    } else {
11854       /* Start a new monitor */
11855       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11856          ast_mutex_unlock(&monlock);
11857          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11858          return -1;
11859       }
11860    }
11861    ast_mutex_unlock(&monlock);
11862    return 0;
11863 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

Definition at line 5176 of file chan_dahdi.c.

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

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

05177 {
05178    int res;
05179    if (p->saveconf.confmode) {
05180       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05181       p->saveconf.confmode = 0;
05182       if (res) {
05183          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05184          return -1;
05185       }
05186       ast_debug(1, "Restored conferencing\n");
05187    }
05188    return 0;
05189 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

Definition at line 5083 of file chan_dahdi.c.

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

Referenced by analog_ss_thread(), dahdi_hangup(), and mwi_thread().

05084 {
05085    int res;
05086 
05087    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05088    if (res) {
05089       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05090       return -1;
05091    }
05092 
05093    return 0;
05094 }

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

Definition at line 6066 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, errno, LOG_WARNING, ast_channel::name, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_hangup().

06067 {
06068    if (p->bufferoverrideinuse) {
06069       /* faxbuffers are in use, revert them */
06070       struct dahdi_bufferinfo bi = {
06071          .txbufpolicy = p->buf_policy,
06072          .rxbufpolicy = p->buf_policy,
06073          .bufsize = p->bufsize,
06074          .numbufs = p->buf_no
06075       };
06076       int bpres;
06077 
06078       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06079          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06080       }
06081       p->bufferoverrideinuse = 0;
06082       return bpres;
06083    }
06084 
06085    return -1;
06086 }

static int save_conference ( struct dahdi_pvt p  )  [static]

Definition at line 5150 of file chan_dahdi.c.

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

Referenced by dahdi_callwait(), dahdi_handle_event(), and my_callwait().

05151 {
05152    struct dahdi_confinfo c;
05153    int res;
05154    if (p->saveconf.confmode) {
05155       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05156       return -1;
05157    }
05158    p->saveconf.chan = 0;
05159    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05160    if (res) {
05161       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05162       p->saveconf.confmode = 0;
05163       return -1;
05164    }
05165    memset(&c, 0, sizeof(c));
05166    c.confmode = DAHDI_CONF_NORMAL;
05167    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05168    if (res) {
05169       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05170       return -1;
05171    }
05172    ast_debug(1, "Disabled conferencing\n");
05173    return 0;
05174 }

static int send_callerid ( struct dahdi_pvt p  )  [static]

Definition at line 5234 of file chan_dahdi.c.

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

Referenced by dahdi_callwait(), dahdi_read(), my_callwait(), my_send_callerid(), and send_cwcidspill().

05235 {
05236    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05237    int res;
05238    /* Take out of linear mode if necessary */
05239    if (p->subs[SUB_REAL].linear) {
05240       p->subs[SUB_REAL].linear = 0;
05241       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05242    }
05243    while (p->cidpos < p->cidlen) {
05244       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05245       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05246       if (res < 0) {
05247          if (errno == EAGAIN)
05248             return 0;
05249          else {
05250             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05251             return -1;
05252          }
05253       }
05254       if (!res)
05255          return 0;
05256       p->cidpos += res;
05257    }
05258    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05259    ast_free(p->cidspill);
05260    p->cidspill = NULL;
05261    if (p->callwaitcas) {
05262       /* Wait for CID/CW to expire */
05263       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05264       p->cid_suppress_expire = p->cidcwexpire;
05265    } else
05266       restore_conference(p);
05267    return 0;
05268 }

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

Definition at line 5191 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::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, MAX_CALLERID_SIZE, READ_SIZE, and send_callerid().

Referenced by dahdi_handle_dtmf().

05192 {
05193    p->callwaitcas = 0;
05194    p->cidcwexpire = 0;
05195    p->cid_suppress_expire = 0;
05196    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05197       return -1;
05198    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05199    /* Make sure we account for the end */
05200    p->cidlen += READ_SIZE * 4;
05201    p->cidpos = 0;
05202    send_callerid(p);
05203    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05204    return 0;
05205 }

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

Definition at line 5064 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

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

05065 {
05066    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05067 }

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

Definition at line 5047 of file chan_dahdi.c.

References ast_debug, errno, and fill_rxgain().

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

05048 {
05049    struct dahdi_gains g;
05050    int res;
05051 
05052    memset(&g, 0, sizeof(g));
05053    res = ioctl(fd, DAHDI_GETGAINS, &g);
05054    if (res) {
05055       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05056       return res;
05057    }
05058 
05059    fill_rxgain(&g, gain, drc, law);
05060 
05061    return ioctl(fd, DAHDI_SETGAINS, &g);
05062 }

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

Definition at line 5030 of file chan_dahdi.c.

References ast_debug, errno, and fill_txgain().

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

05031 {
05032    struct dahdi_gains g;
05033    int res;
05034 
05035    memset(&g, 0, sizeof(g));
05036    res = ioctl(fd, DAHDI_GETGAINS, &g);
05037    if (res) {
05038       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05039       return res;
05040    }
05041 
05042    fill_txgain(&g, gain, drc, law);
05043 
05044    return ioctl(fd, DAHDI_SETGAINS, &g);
05045 }

static int setup_dahdi ( int  reload  )  [static]

Definition at line 18254 of file chan_dahdi.c.

References ast_cc_config_params_destroy(), dahdi_pvt::cc_params, dahdi_chan_conf::chan, dahdi_chan_conf_default(), and setup_dahdi_int().

Referenced by load_module(), and reload().

18255 {
18256    int res;
18257    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18258    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18259    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18260 
18261    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18262       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18263    } else {
18264       res = -1;
18265    }
18266    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18267    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18268    ast_cc_config_params_destroy(conf.chan.cc_params);
18269 
18270    return res;
18271 }

static int setup_dahdi_int ( int  reload,
struct dahdi_chan_conf default_conf,
struct dahdi_chan_conf base_conf,
struct dahdi_chan_conf conf 
) [static]

Definition at line 17967 of file chan_dahdi.c.

References ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_config_new(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, config, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, deep_copy_dahdi_chan_conf(), default_jbconf, global_jbconf, ast_variable::lineno, LOG_NOTICE, mwimonitornotify, ast_variable::name, ast_variable::next, prepare_pri(), pri_create_spanmap(), pri_create_trunkgroup(), PROC_DAHDI_OPT_NOWARN, process_dahdi(), sig_pri_start_pri(), and ast_variable::value.

Referenced by setup_dahdi().

17968 {
17969    struct ast_config *cfg;
17970    struct ast_config *ucfg;
17971    struct ast_variable *v;
17972    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17973    const char *chans;
17974    const char *cat;
17975    int res;
17976 
17977 #ifdef HAVE_PRI
17978    char *c;
17979    int spanno;
17980    int i;
17981    int logicalspan;
17982    int trunkgroup;
17983    int dchannels[SIG_PRI_NUM_DCHANS];
17984 #endif
17985    int have_cfg_now;
17986    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
17987 
17988    cfg = ast_config_load(config, config_flags);
17989    have_cfg_now = !!cfg;
17990    if (!cfg) {
17991       /* Error if we have no config file */
17992       if (had_cfg_before) {
17993          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17994          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17995       }
17996       cfg = ast_config_new();/* Dummy config */
17997       if (!cfg) {
17998          return 0;
17999       }
18000       ucfg = ast_config_load("users.conf", config_flags);
18001       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18002          ast_config_destroy(cfg);
18003          return 0;
18004       }
18005       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18006          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18007          ast_config_destroy(cfg);
18008          return 0;
18009       }
18010    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18011       ucfg = ast_config_load("users.conf", config_flags);
18012       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18013          return 0;
18014       }
18015       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18016          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18017          return 0;
18018       }
18019       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18020       cfg = ast_config_load(config, config_flags);
18021       have_cfg_now = !!cfg;
18022       if (!cfg) {
18023          if (had_cfg_before) {
18024             /* We should have been able to load the config. */
18025             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18026             ast_config_destroy(ucfg);
18027             return 0;
18028          }
18029          cfg = ast_config_new();/* Dummy config */
18030          if (!cfg) {
18031             ast_config_destroy(ucfg);
18032             return 0;
18033          }
18034       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18035          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18036          ast_config_destroy(ucfg);
18037          return 0;
18038       }
18039    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18040       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18041       return 0;
18042    } else {
18043       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18044       ucfg = ast_config_load("users.conf", config_flags);
18045       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18046          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18047          ast_config_destroy(cfg);
18048          return 0;
18049       }
18050    }
18051    had_cfg_before = have_cfg_now;
18052 
18053    /* It's a little silly to lock it, but we might as well just to be sure */
18054    ast_mutex_lock(&iflock);
18055 #ifdef HAVE_PRI
18056    if (reload != 1) {
18057       /* Process trunkgroups first */
18058       v = ast_variable_browse(cfg, "trunkgroups");
18059       while (v) {
18060          if (!strcasecmp(v->name, "trunkgroup")) {
18061             trunkgroup = atoi(v->value);
18062             if (trunkgroup > 0) {
18063                if ((c = strchr(v->value, ','))) {
18064                   i = 0;
18065                   memset(dchannels, 0, sizeof(dchannels));
18066                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18067                      dchannels[i] = atoi(c + 1);
18068                      if (dchannels[i] < 0) {
18069                         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);
18070                      } else
18071                         i++;
18072                      c = strchr(c + 1, ',');
18073                   }
18074                   if (i) {
18075                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18076                         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);
18077                   } else
18078                         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");
18079                   } else
18080                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18081                } else
18082                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18083             } else
18084                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18085          } else if (!strcasecmp(v->name, "spanmap")) {
18086             spanno = atoi(v->value);
18087             if (spanno > 0) {
18088                if ((c = strchr(v->value, ','))) {
18089                   trunkgroup = atoi(c + 1);
18090                   if (trunkgroup > 0) {
18091                      if ((c = strchr(c + 1, ',')))
18092                         logicalspan = atoi(c + 1);
18093                      else
18094                         logicalspan = 0;
18095                      if (logicalspan >= 0) {
18096                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18097                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18098                      } else
18099                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18100                      } else
18101                         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);
18102                   } else
18103                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18104                } else
18105                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18106             } else
18107                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18108          } else {
18109             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18110          }
18111          v = v->next;
18112       }
18113    }
18114 #endif
18115 
18116    /* Copy the default jb config over global_jbconf */
18117    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18118 
18119    mwimonitornotify[0] = '\0';
18120 
18121    v = ast_variable_browse(cfg, "channels");
18122    if ((res = process_dahdi(base_conf,
18123       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18124       v, reload, 0))) {
18125       ast_mutex_unlock(&iflock);
18126       ast_config_destroy(cfg);
18127       if (ucfg) {
18128          ast_config_destroy(ucfg);
18129       }
18130       return res;
18131    }
18132 
18133    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18134    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18135       /* [channels] and [trunkgroups] are used. Let's also reserve
18136        * [globals] and [general] for future use
18137        */
18138       if (!strcasecmp(cat, "general") ||
18139          !strcasecmp(cat, "trunkgroups") ||
18140          !strcasecmp(cat, "globals") ||
18141          !strcasecmp(cat, "channels")) {
18142          continue;
18143       }
18144 
18145       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18146       if (ast_strlen_zero(chans)) {
18147          /* Section is useless without a dahdichan value present. */
18148          continue;
18149       }
18150 
18151       /* Copy base_conf to conf. */
18152       deep_copy_dahdi_chan_conf(conf, base_conf);
18153 
18154       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18155          ast_mutex_unlock(&iflock);
18156          ast_config_destroy(cfg);
18157          if (ucfg) {
18158             ast_config_destroy(ucfg);
18159          }
18160          return res;
18161       }
18162    }
18163 
18164    ast_config_destroy(cfg);
18165 
18166    if (ucfg) {
18167       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18168       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18169       process_dahdi(base_conf,
18170          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18171          ast_variable_browse(ucfg, "general"), 1, 0);
18172 
18173       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18174          if (!strcasecmp(cat, "general")) {
18175             continue;
18176          }
18177 
18178          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18179          if (ast_strlen_zero(chans)) {
18180             /* Section is useless without a dahdichan value present. */
18181             continue;
18182          }
18183 
18184          /* Copy base_conf to conf. */
18185          deep_copy_dahdi_chan_conf(conf, base_conf);
18186 
18187          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18188             ast_config_destroy(ucfg);
18189             ast_mutex_unlock(&iflock);
18190             return res;
18191          }
18192       }
18193       ast_config_destroy(ucfg);
18194    }
18195    ast_mutex_unlock(&iflock);
18196 
18197 #ifdef HAVE_PRI
18198    if (reload != 1) {
18199       int x;
18200       for (x = 0; x < NUM_SPANS; x++) {
18201          if (pris[x].pri.pvts[0]) {
18202             prepare_pri(pris + x);
18203             if (sig_pri_start_pri(&pris[x].pri)) {
18204                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18205                return -1;
18206             } else
18207                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18208          }
18209       }
18210    }
18211 #endif
18212 #if defined(HAVE_SS7)
18213    if (reload != 1) {
18214       int x;
18215       for (x = 0; x < NUM_SPANS; x++) {
18216          if (linksets[x].ss7.ss7) {
18217             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18218             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18219                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18220                return -1;
18221             } else
18222                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18223          }
18224       }
18225    }
18226 #endif   /* defined(HAVE_SS7) */
18227 #ifdef HAVE_OPENR2
18228    if (reload != 1) {
18229       int x;
18230       for (x = 0; x < r2links_count; x++) {
18231          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18232             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18233             return -1;
18234          } else {
18235             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18236          }
18237       }
18238    }
18239 #endif
18240    /* And start the monitor for the first time */
18241    restart_monitor();
18242    return 0;
18243 }

static int sig_pri_tone_to_dahditone ( enum sig_pri_tone  tone  )  [static]

Definition at line 3049 of file chan_dahdi.c.

References SIG_PRI_TONE_BUSY, SIG_PRI_TONE_CONGESTION, SIG_PRI_TONE_DIALRECALL, SIG_PRI_TONE_DIALTONE, SIG_PRI_TONE_INFO, SIG_PRI_TONE_RINGTONE, and SIG_PRI_TONE_STUTTER.

Referenced by my_pri_play_tone().

03050 {
03051    switch (tone) {
03052    case SIG_PRI_TONE_RINGTONE:
03053       return DAHDI_TONE_RINGTONE;
03054    case SIG_PRI_TONE_STUTTER:
03055       return DAHDI_TONE_STUTTER;
03056    case SIG_PRI_TONE_CONGESTION:
03057       return DAHDI_TONE_CONGESTION;
03058    case SIG_PRI_TONE_DIALTONE:
03059       return DAHDI_TONE_DIALTONE;
03060    case SIG_PRI_TONE_DIALRECALL:
03061       return DAHDI_TONE_DIALRECALL;
03062    case SIG_PRI_TONE_INFO:
03063       return DAHDI_TONE_INFO;
03064    case SIG_PRI_TONE_BUSY:
03065       return DAHDI_TONE_BUSY;
03066    default:
03067       return -1;
03068    }
03069 }

static int sig_ss7_tone_to_dahditone ( enum sig_ss7_tone  tone  )  [static]

Definition at line 3474 of file chan_dahdi.c.

References SIG_SS7_TONE_BUSY, SIG_SS7_TONE_CONGESTION, SIG_SS7_TONE_DIALRECALL, SIG_SS7_TONE_DIALTONE, SIG_SS7_TONE_INFO, SIG_SS7_TONE_RINGTONE, and SIG_SS7_TONE_STUTTER.

Referenced by my_ss7_play_tone().

03475 {
03476    switch (tone) {
03477    case SIG_SS7_TONE_RINGTONE:
03478       return DAHDI_TONE_RINGTONE;
03479    case SIG_SS7_TONE_STUTTER:
03480       return DAHDI_TONE_STUTTER;
03481    case SIG_SS7_TONE_CONGESTION:
03482       return DAHDI_TONE_CONGESTION;
03483    case SIG_SS7_TONE_DIALTONE:
03484       return DAHDI_TONE_DIALTONE;
03485    case SIG_SS7_TONE_DIALRECALL:
03486       return DAHDI_TONE_DIALRECALL;
03487    case SIG_SS7_TONE_INFO:
03488       return DAHDI_TONE_INFO;
03489    case SIG_SS7_TONE_BUSY:
03490       return DAHDI_TONE_BUSY;
03491    default:
03492       return -1;
03493    }
03494 }

static int sigtype_to_signalling ( int  sigtype  )  [static]

Definition at line 12115 of file chan_dahdi.c.

12116 {
12117    return sigtype;
12118 }

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

Definition at line 12004 of file chan_dahdi.c.

References linksets, and NUM_SPANS.

Referenced by linkset_addsigchan().

12005 {
12006    if ((linkset < 0) || (linkset >= NUM_SPANS))
12007       return NULL;
12008    else
12009       return &linksets[linkset - 1];
12010 }

static void string_replace ( char *  str,
int  char1,
int  char2 
) [static]

Definition at line 16677 of file chan_dahdi.c.

Referenced by parse_spanchan().

16678 {
16679    for (; *str; str++) {
16680       if (*str == char1) {
16681          *str = char2;
16682       }
16683    }
16684 }

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

Definition at line 4222 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 analog_ss_thread(), attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), HandleCallOutgoing(), and unistim_hangup().

04223 {
04224    int tchan;
04225    int tinthreeway;
04226    struct ast_channel *towner;
04227 
04228    ast_debug(1, "Swapping %d and %d\n", a, b);
04229 
04230    tchan = p->subs[a].chan;
04231    towner = p->subs[a].owner;
04232    tinthreeway = p->subs[a].inthreeway;
04233 
04234    p->subs[a].chan = p->subs[b].chan;
04235    p->subs[a].owner = p->subs[b].owner;
04236    p->subs[a].inthreeway = p->subs[b].inthreeway;
04237 
04238    p->subs[b].chan = tchan;
04239    p->subs[b].owner = towner;
04240    p->subs[b].inthreeway = tinthreeway;
04241 
04242    if (p->subs[a].owner)
04243       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04244    if (p->subs[b].owner)
04245       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04246    wakeup_sub(p, a);
04247    wakeup_sub(p, b);
04248 }

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

Definition at line 4368 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 analog_ss_thread(), attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), my_unallocate_sub(), and unistim_hangup().

04369 {
04370    if (!x) {
04371       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04372       return -1;
04373    }
04374    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04375    dahdi_close_sub(p, x);
04376    p->subs[x].linear = 0;
04377    p->subs[x].chan = 0;
04378    p->subs[x].owner = NULL;
04379    p->subs[x].inthreeway = 0;
04380    p->polarity = POLARITY_IDLE;
04381    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04382    return 0;
04383 }

static int unload_module ( void   )  [static]

Definition at line 16661 of file chan_dahdi.c.

References __unload_module(), ast_mutex_destroy, sig_ss7_linkset::lock, sig_pri_span::lock, dahdi_pvt::pri, and dahdi_pvt::ss7.

16662 {
16663 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16664    int y;
16665 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16666 #ifdef HAVE_PRI
16667    for (y = 0; y < NUM_SPANS; y++)
16668       ast_mutex_destroy(&pris[y].pri.lock);
16669 #endif
16670 #if defined(HAVE_SS7)
16671    for (y = 0; y < NUM_SPANS; y++)
16672       ast_mutex_destroy(&linksets[y].ss7.lock);
16673 #endif   /* defined(HAVE_SS7) */
16674    return __unload_module();
16675 }

static int update_conf ( struct dahdi_pvt p  )  [static]

Definition at line 4777 of file chan_dahdi.c.

References conf_add(), conf_del(), dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, isslavenative(), and dahdi_pvt::subs.

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

04778 {
04779    int needconf = 0;
04780    int x;
04781    int useslavenative;
04782    struct dahdi_pvt *slave = NULL;
04783 
04784    useslavenative = isslavenative(p, &slave);
04785    /* Start with the obvious, general stuff */
04786    for (x = 0; x < 3; x++) {
04787       /* Look for three way calls */
04788       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04789          conf_add(p, &p->subs[x], x, 0);
04790          needconf++;
04791       } else {
04792          conf_del(p, &p->subs[x], x);
04793       }
04794    }
04795    /* If we have a slave, add him to our conference now. or DAX
04796       if this is slave native */
04797    for (x = 0; x < MAX_SLAVES; x++) {
04798       if (p->slaves[x]) {
04799          if (useslavenative)
04800             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04801          else {
04802             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04803             needconf++;
04804          }
04805       }
04806    }
04807    /* If we're supposed to be in there, do so now */
04808    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04809       if (useslavenative)
04810          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04811       else {
04812          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04813          needconf++;
04814       }
04815    }
04816    /* If we have a master, add ourselves to his conference */
04817    if (p->master) {
04818       if (isslavenative(p->master, NULL)) {
04819          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04820       } else {
04821          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04822       }
04823    }
04824    if (!needconf) {
04825       /* Nobody is left (or should be left) in our conference.
04826          Kill it. */
04827       p->confno = -1;
04828    }
04829    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04830    return 0;
04831 }

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

Definition at line 3735 of file chan_dahdi.c.

References ast_channel_unlock, ast_null_frame, ast_queue_frame(), dahdi_lock_sub_owner(), dahdi_subchannel::owner, and dahdi_pvt::subs.

Referenced by my_swap_subchannels(), and swap_subs().

03736 {
03737    dahdi_lock_sub_owner(p, a);
03738    if (p->subs[a].owner) {
03739       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03740       ast_channel_unlock(p->subs[a].owner);
03741    }
03742 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = tdesc , .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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_smdi", } [static]

Definition at line 18633 of file chan_dahdi.c.

int alarm

Definition at line 4515 of file chan_dahdi.c.

Referenced by alarm2str().

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

Referenced by alarm2str().

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

Definition at line 406 of file chan_dahdi.c.

Referenced by mwi_send_process_buffer().

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 18633 of file chan_dahdi.c.

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

Definition at line 387 of file chan_dahdi.c.

Referenced by handle_dahdi_show_cadences(), and my_set_cadence().

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

Referenced by handle_dahdi_show_cadences().

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

Definition at line 341 of file chan_dahdi.c.

int cur_adjpointcode = -1 [static]

Definition at line 542 of file chan_dahdi.c.

Referenced by linkset_addsigchan().

int cur_cicbeginswith = -1 [static]

Definition at line 541 of file chan_dahdi.c.

int cur_defaultdpc = -1 [static]

Definition at line 544 of file chan_dahdi.c.

Referenced by linkset_addsigchan().

int cur_linkset = -1 [static]

Definition at line 539 of file chan_dahdi.c.

Referenced by linkset_addsigchan().

int cur_networkindicator = -1 [static]

Definition at line 543 of file chan_dahdi.c.

Referenced by linkset_addsigchan().

int cur_pointcode = -1 [static]

Definition at line 540 of file chan_dahdi.c.

Referenced by linkset_addsigchan().

int cur_ss7type = -1 [static]

Definition at line 538 of file chan_dahdi.c.

Referenced by linkset_addsigchan().

const char* const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" [static]

Definition at line 5924 of file chan_dahdi.c.

struct analog_callback dahdi_analog_callbacks [static]

Definition at line 3612 of file chan_dahdi.c.

struct ast_data_handler dahdi_channels_data_provider [static]

Initial value:

Definition at line 18414 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

Definition at line 15735 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_data_entry dahdi_data_providers[] [static]

Initial value:

 {
   AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
   AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),

}

Definition at line 18424 of file chan_dahdi.c.

Referenced by load_module().

struct ast_cli_entry dahdi_mfcr2_cli[] [static]

Definition at line 14889 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct sig_pri_callback dahdi_pri_callbacks [static]

Definition at line 3340 of file chan_dahdi.c.

Referenced by prepare_pri().

struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks [static]

Definition at line 16541 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks [static]

Definition at line 16559 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

const char dahdi_pri_cc_type[] = "DAHDI/PRI" [static]

DAHDI PRI CCSS agent and monitor type name.

Definition at line 599 of file chan_dahdi.c.

Referenced by dahdi_queryoption(), and load_module().

struct ast_cli_entry dahdi_pri_cli[] [static]

Definition at line 14553 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct dahdi_parms_pseudo dahdi_pseudo_parms [static]

openr2_event_interface_t dahdi_r2_event_iface [static]

Definition at line 4184 of file chan_dahdi.c.

openr2_transcoder_interface_t dahdi_r2_transcode_iface [static]

Initial value:

Definition at line 4215 of file chan_dahdi.c.

char* dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility" [static]

Definition at line 5861 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

Definition at line 5834 of file chan_dahdi.c.

struct sig_ss7_callback dahdi_ss7_callbacks [static]

Definition at line 3507 of file chan_dahdi.c.

struct ast_cli_entry dahdi_ss7_cli[] [static]

Definition at line 16455 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_data_handler dahdi_status_data_provider [static]

Initial value:

Definition at line 18409 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 1512 of file chan_dahdi.c.

Referenced by __unload_module(), analog_ss_thread(), dahdi_accept_r2_call_exec(), dahdi_new(), dahdi_send_callrerouting_facility_exec(), and load_module().

struct ast_data_handler dahdi_version_data_provider [static]

Initial value:

Definition at line 18419 of file chan_dahdi.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Note:
Values shown here match the defaults shown in chan_dahdi.conf.sample

Definition at line 290 of file chan_dahdi.c.

char defaultcic[64] = "" [static]

Definition at line 414 of file chan_dahdi.c.

char defaultozz[64] = "" [static]

Definition at line 415 of file chan_dahdi.c.

int distinctiveringaftercid = 0 [static]

Definition at line 426 of file chan_dahdi.c.

int dtmfcid_level = 256 [static]

Definition at line 431 of file chan_dahdi.c.

const char* const events[] [static]

Definition at line 4492 of file chan_dahdi.c.

int firstdigittimeout = 16000 [static]

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

Definition at line 443 of file chan_dahdi.c.

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

int gendigittimeout = 8000 [static]

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

Definition at line 446 of file chan_dahdi.c.

Referenced by analog_ss_thread(), and mgcp_ss().

struct ast_jb_conf global_jbconf [static]

Definition at line 298 of file chan_dahdi.c.

int ifcount = 0 [static]

Definition at line 455 of file chan_dahdi.c.

Referenced by destroy_all_channels(), and do_monitor().

struct dahdi_pvt* ifend = NULL [static]

Main interface list end

Definition at line 1316 of file chan_dahdi.c.

Referenced by dahdi_iflist_extract(), dahdi_request(), and determine_starting_point().

struct dahdi_pvt* iflist = NULL [static]

Main interface list start

Definition at line 1315 of file chan_dahdi.c.

Referenced by __oh323_destroy(), __unload_module(), action_dahdishowchannels(), dahdi_channels_data_provider_get(), dahdi_destroy_channel_bynum(), dahdi_iflist_extract(), dahdi_iflist_insert(), dahdi_request(), dahdi_set_dnd(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), determine_starting_point(), do_monitor(), find_call_locked(), find_channel(), handle_mfcr2_call_files(), handle_mfcr2_set_blocked(), handle_mfcr2_set_debug(), handle_mfcr2_set_idle(), handle_mfcr2_show_channels(), load_module(), mkintf(), oh323_alloc(), phone_request(), and unload_module().

ast_mutex_t iflock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Protect the interface list (of dahdi_pvt's).

Definition at line 452 of file chan_dahdi.c.

Referenced by __unload_module(), dahdi_cc_callback(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), destroy_all_channels(), do_monitor(), find_call_locked(), load_module(), oh323_alloc(), oh323_destroy(), phone_request(), restart_monitor(), and unload_module().

const char* const lbostr[] [static]

Definition at line 277 of file chan_dahdi.c.

Referenced by dahdi_show_status(), and dahdi_status_data_provider_get().

struct dahdi_ss7 linksets[NUM_SPANS] [static]

Definition at line 536 of file chan_dahdi.c.

Referenced by dahdi_ss7_error(), dahdi_ss7_message(), and ss7_resolve_linkset().

int matchdigittimeout = 3000 [static]

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

Definition at line 449 of file chan_dahdi.c.

Referenced by analog_ss_thread(), and mgcp_ss().

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

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

Definition at line 467 of file chan_dahdi.c.

Referenced by __sip_reliable_xmit(), __unload_module(), restart_monitor(), and unload_module().

ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [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 463 of file chan_dahdi.c.

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

int mwilevel = 512 [static]

Definition at line 430 of file chan_dahdi.c.

Referenced by mwi_thread().

char mwimonitornotify[PATH_MAX] = "" [static]

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

Definition at line 418 of file chan_dahdi.c.

Referenced by notify_message(), and setup_dahdi_int().

char* name

Definition at line 4516 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 384 of file chan_dahdi.c.

Referenced by handle_dahdi_show_cadences(), and my_set_cadence().

int num_restart_pending = 0 [static]

Definition at line 472 of file chan_dahdi.c.

Referenced by dahdi_hangup(), dahdi_softhangup_all(), destroy_all_channels(), and my_all_subchannels_hungup().

int numbufs = 4 [static]

Definition at line 428 of file chan_dahdi.c.

int pridebugfd = -1 [static]

Definition at line 438 of file chan_dahdi.c.

Referenced by handle_pri_set_debug_file().

ast_mutex_t pridebugfdlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 458 of file chan_dahdi.c.

Referenced by handle_pri_set_debug_file().

char pridebugfilename[1024] = "" [static]

Definition at line 439 of file chan_dahdi.c.

Referenced by handle_pri_set_debug_file().

struct dahdi_pri pris[NUM_SPANS] [static]

Definition at line 595 of file chan_dahdi.c.

Referenced by complete_span_helper(), dahdi_devicestate(), dahdi_pri_error(), dahdi_pri_message(), dahdi_restart(), destroy_all_channels(), handle_pri_debug(), handle_pri_service_generic(), handle_pri_show_channels(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), prepare_pri(), pri_create_spanmap(), pri_create_trunkgroup(), and pri_resolve_span().

char progzone[10] = "" [static]

Definition at line 423 of file chan_dahdi.c.

Referenced by dahdi_new().

struct dahdi_mfcr2** r2links [static]

Definition at line 580 of file chan_dahdi.c.

Referenced by dahdi_r2_destroy_links(), and dahdi_r2_get_link().

int r2links_count = 0 [static]

Definition at line 582 of file chan_dahdi.c.

Referenced by dahdi_r2_destroy_links(), and dahdi_r2_get_link().

int report_alarms = REPORT_CHANNEL_ALARMS [static]

Definition at line 435 of file chan_dahdi.c.

Referenced by handle_alarms(), and handle_clear_alarms().

ast_mutex_t restart_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

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

struct dahdi_pvt* round_robin[32] [static]

Round robin search locations.

Definition at line 3682 of file chan_dahdi.c.

Referenced by dahdi_request(), determine_starting_point(), and load_module().

ast_cond_t ss_thread_complete [static]

Definition at line 468 of file chan_dahdi.c.

Referenced by __unload_module(), load_module(), and my_decrease_ss_count().

int ss_thread_count = 0 [static]

Definition at line 471 of file chan_dahdi.c.

Referenced by analog_ss_thread(), my_decrease_ss_count(), and my_increase_ss_count().

ast_mutex_t ss_thread_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 469 of file chan_dahdi.c.

Referenced by analog_ss_thread(), my_decrease_ss_count(), and my_increase_ss_count().

const char* const subnames[] [static]

Initial value:

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

Definition at line 628 of file chan_dahdi.c.

Referenced by alloc_sub(), dahdi_bridge(), and dahdi_new().

const char tdesc[] [static]

Definition at line 320 of file chan_dahdi.c.

int usedistinctiveringdetection = 0 [static]

Definition at line 425 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 385 of file chan_dahdi.c.


Generated on Sat Mar 10 01:54:54 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7