Mon Aug 31 12:30:22 2015

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 "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_pvt
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 CIDCW_EXPIRE_SAMPLES   ((500 * 8) / READ_SIZE)
#define CONF_USER_REAL   (1 << 0)
#define CONF_USER_THIRDCALL   (1 << 1)
#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 %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define FORMAT2   "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT2   "%7s %-15.15s %-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 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_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 }
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 int __unload_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)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DRIVER,.nonoptreq="res_smdi",)
 AST_MUTEX_DEFINE_STATIC (restart_lock)
 AST_MUTEX_DEFINE_STATIC (ss_thread_lock)
 AST_MUTEX_DEFINE_STATIC (monlock)
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
 AST_MUTEX_DEFINE_STATIC (iflock)
 Protect the interface list (of dahdi_pvt's).
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 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)
static void dahdi_ami_channel_event (struct dahdi_pvt *p, struct ast_channel *chan)
static int dahdi_answer (struct ast_channel *ast)
static enum ast_bridge_result dahdi_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int dahdi_call (struct ast_channel *ast, char *rdest, int timeout)
static int dahdi_callwait (struct ast_channel *ast)
static 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_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_open (char *fn)
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 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_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_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 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 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 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 load_module (void)
static struct dahdi_pvtmkintf (int channel, const struct dahdi_chan_conf *conf, int reloading)
static void monitor_pfds_clean (void *arg)
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_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_dtmf (void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
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 struct ast_channelmy_new_analog_ast_channel (void *pvt, int state, int startpbx, enum analog_sub sub, 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 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 *cid_rings, struct ast_channel *ast)
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 int my_set_echocanceller (void *pvt, int enable)
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_needringing (void *pvt, int value)
static void my_set_new_owner (void *pvt, struct ast_channel *new_owner)
static void my_set_outgoing (void *pvt, int is_outgoing)
static void my_set_polarity (void *pvt, int value)
static void my_set_pulsedial (void *pvt, int flag)
static void my_set_ringtimeout (void *pvt, int ringt)
static void my_set_waitingfordt (void *pvt, struct ast_channel *ast)
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 char * parse_spanchan (char *chanstr, char **subdir)
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 sigtype_to_signalling (int sigtype)
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

struct {
   int   alarm
   char *   name
alarms []
static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
static int cidrings [NUM_CADENCE_MAX]
 cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.
static const char config [] = "chan_dahdi.conf"
static struct 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_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 const char *const lbostr []
static int matchdigittimeout = 3000
 How long to wait for an extra digit, if there is an ambiguous match.
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use.
static int mwilevel = 512
static char mwimonitornotify [PATH_MAX] = ""
static int mwisend_rpas = 0
static int num_cadence = 4
static int num_restart_pending = 0
static int numbufs = 4
static char progzone [10] = ""
static int report_alarms = REPORT_CHANNEL_ALARMS
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 const char *const subnames []
static const char tdesc [] = "DAHDI Telephony Driver"
static int usedistinctiveringdetection = 0
static int user_has_defined_cadences = 0

Detailed Description

DAHDI for Pseudo TDM.

Author:
Mark Spencer <markster@digium.com>

Connects to the DAHDI telephony library as well as libpri. Libpri is optional and needed only if you are going to use ISDN connections.

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

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

Definition in file chan_dahdi.c.


Define Documentation

#define ASCII_BYTES_PER_CHAR   80

Referenced by dahdi_sendtext().

#define AST_LAW (  )     (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)

Definition at line 387 of file chan_dahdi.c.

Referenced by dahdi_handle_dtmf(), my_handle_dtmf(), and process_dahdi().

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 386 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 385 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_PROGRESS   1

Definition at line 384 of file chan_dahdi.c.

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

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

10,000 ms

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

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

100 ms

Definition at line 523 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 417 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) */)
#define CHAN_PSEUDO   -2
#define CIDCW_EXPIRE_SAMPLES   ((500 * 8) / READ_SIZE)

500 ms

Definition at line 524 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 659 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 660 of file chan_dahdi.c.

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

Definition at line 1251 of file chan_dahdi.c.

#define DEFAULT_CIDRINGS   1

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

Note:
Define ZHONE_HACK to cause us to go off hook and then back on hook when the user hangs up to reset the state machine so ring works properly. This is used to be able to support kewlstart by putting the zhone in groundstart mode since their forward disconnect supervision is entirely broken even though their documentation says it isn't and their support is entirely unwilling to provide any assistance with their channel banks even though their web site says they support their products for life.

Definition at line 318 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

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

8,000 ms

Definition at line 526 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 %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define FORMAT2   "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT2   "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define GET_CHANNEL (  )     ((p)->channel)

Definition at line 1546 of file chan_dahdi.c.

Referenced by my_complete_conference_update(), and update_conf().

#define HANGUP   1

Definition at line 16056 of file chan_dahdi.c.

Referenced by action_transferhangup(), and dahdi_fake_event().

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

Referenced by dahdi_sendtext().

#define ISTRUNK (  ) 
Value:
((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
         (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))

Definition at line 414 of file chan_dahdi.c.

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

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 518 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

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

2000 ms

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

Referenced by analog_ss_thread(), and dahdi_new().

#define NUM_CADENCE_MAX   25

Definition at line 389 of file chan_dahdi.c.

Referenced by process_dahdi().

#define NUM_SPANS   32

Definition at line 379 of file chan_dahdi.c.

Referenced by destroy_all_channels().

#define POLARITY_IDLE   0
#define POLARITY_REV   1
#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)

process_dahdi() - ignore keyword 'channel' and similar

Definition at line 17138 of file chan_dahdi.c.

Referenced by process_dahdi(), and setup_dahdi_int().

#define PROC_DAHDI_OPT_NOWARN   (1 << 1)

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

Definition at line 17140 of file chan_dahdi.c.

Referenced by process_dahdi(), and setup_dahdi_int().

#define READ_SIZE   160

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

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

#define REPORT_CHANNEL_ALARMS   1

Definition at line 439 of file chan_dahdi.c.

Referenced by handle_alarms(), handle_clear_alarms(), and process_dahdi().

#define REPORT_SPAN_ALARMS   2

Definition at line 440 of file chan_dahdi.c.

Referenced by handle_alarms(), handle_clear_alarms(), and process_dahdi().

#define sig2str   dahdi_sig2str
#define SIG_BRI   (0x2000000 | DAHDI_SIG_CLEAR)

Definition at line 365 of file chan_dahdi.c.

Referenced by dahdi_sig2str(), and process_dahdi().

#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)

Definition at line 366 of file chan_dahdi.c.

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

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

Definition at line 364 of file chan_dahdi.c.

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

#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

Definition at line 281 of file chan_dahdi.c.

Referenced by analog_ss_thread().

#define SUB_CALLWAIT   1
#define SUB_REAL   0

Active call

Definition at line 614 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_read(), dahdi_request(), dahdi_restart(), 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(), mkintf(), 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_off_hook(), my_set_cadence(), my_set_needringing(), my_set_polarity(), 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(), unistim_senddigit_end(), and update_conf().

#define SUB_THREEWAY   2
#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

Enumeration Type Documentation

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

Definition at line 683 of file chan_dahdi.c.

00683                   {
00684    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00685    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00686 #if defined(HAVE_PRI)
00687    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00688 #endif   /* defined(HAVE_PRI) */
00689 };

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

00667              {
00668    MWI_SEND_NULL = 0,
00669    MWI_SEND_SA,
00670    MWI_SEND_SA_WAIT,
00671    MWI_SEND_PAUSE,
00672    MWI_SEND_SPILL,
00673    MWI_SEND_CLEANUP,
00674    MWI_SEND_DONE,
00675 } mwisend_states;


Function Documentation

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

Definition at line 8819 of file chan_dahdi.c.

References ast_channel::_state, ast_bridged_channel(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_NULL, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_queue_control(), ast_set_hangupsource(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_strdupa, ast_tv(), ast_tvnow(), ast_verb, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index, dahdi_handle_event(), dahdi_ring_phone(), dahdi_set_hook(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_pvt::dialing, event2str(), dahdi_subchannel::f, dahdi_pvt::fake_event, ast_channel::fds, dahdi_pvt::flashtime, ast_frame::frametype, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_WARNING, ast_frame::mallocd, name, dahdi_subchannel::needanswer, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, ast_frame::ptr, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().

Referenced by dahdi_exception(), and dahdi_read().

08820 {
08821    int res;
08822    int idx;
08823    struct ast_frame *f;
08824    int usedindex = -1;
08825    struct dahdi_pvt *p = ast->tech_pvt;
08826 
08827    if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08828       idx = SUB_REAL;
08829    }
08830 
08831    p->subs[idx].f.frametype = AST_FRAME_NULL;
08832    p->subs[idx].f.datalen = 0;
08833    p->subs[idx].f.samples = 0;
08834    p->subs[idx].f.mallocd = 0;
08835    p->subs[idx].f.offset = 0;
08836    p->subs[idx].f.subclass.integer = 0;
08837    p->subs[idx].f.delivery = ast_tv(0,0);
08838    p->subs[idx].f.src = "dahdi_exception";
08839    p->subs[idx].f.data.ptr = NULL;
08840 
08841 
08842    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08843       /* If nobody owns us, absorb the event appropriately, otherwise
08844          we loop indefinitely.  This occurs when, during call waiting, the
08845          other end hangs up our channel so that it no longer exists, but we
08846          have neither FLASH'd nor ONHOOK'd to signify our desire to
08847          change to the other channel. */
08848       if (p->fake_event) {
08849          res = p->fake_event;
08850          p->fake_event = 0;
08851       } else
08852          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08853       /* Switch to real if there is one and this isn't something really silly... */
08854       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08855          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08856          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08857          p->owner = p->subs[SUB_REAL].owner;
08858          if (p->owner && ast_bridged_channel(p->owner))
08859             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08860          p->subs[SUB_REAL].needunhold = 1;
08861       }
08862       switch (res) {
08863       case DAHDI_EVENT_ONHOOK:
08864          dahdi_disable_ec(p);
08865          if (p->owner) {
08866             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08867             dahdi_ring_phone(p);
08868             p->callwaitingrepeat = 0;
08869             p->cidcwexpire = 0;
08870             p->cid_suppress_expire = 0;
08871          } else
08872             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08873          update_conf(p);
08874          break;
08875       case DAHDI_EVENT_RINGOFFHOOK:
08876          dahdi_enable_ec(p);
08877          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08878          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08879             p->subs[SUB_REAL].needanswer = 1;
08880             p->dialing = 0;
08881          }
08882          break;
08883       case DAHDI_EVENT_HOOKCOMPLETE:
08884       case DAHDI_EVENT_RINGERON:
08885       case DAHDI_EVENT_RINGEROFF:
08886          /* Do nothing */
08887          break;
08888       case DAHDI_EVENT_WINKFLASH:
08889          p->flashtime = ast_tvnow();
08890          if (p->owner) {
08891             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08892             if (p->owner->_state != AST_STATE_UP) {
08893                /* Answer if necessary */
08894                usedindex = dahdi_get_index(p->owner, p, 0);
08895                if (usedindex > -1) {
08896                   p->subs[usedindex].needanswer = 1;
08897                }
08898                ast_setstate(p->owner, AST_STATE_UP);
08899             }
08900             p->callwaitingrepeat = 0;
08901             p->cidcwexpire = 0;
08902             p->cid_suppress_expire = 0;
08903             if (ast_bridged_channel(p->owner))
08904                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08905             p->subs[SUB_REAL].needunhold = 1;
08906          } else
08907             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08908          update_conf(p);
08909          break;
08910       default:
08911          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08912       }
08913       f = &p->subs[idx].f;
08914       return f;
08915    }
08916    if (!(p->radio || (p->oprmode < 0)))
08917       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08918    /* If it's not us, return NULL immediately */
08919    if (ast != p->owner) {
08920       if (p->owner) {
08921          ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08922       }
08923       f = &p->subs[idx].f;
08924       return f;
08925    }
08926 
08927    f = dahdi_handle_event(ast);
08928    if (!f) {
08929       const char *name = ast_strdupa(ast->name);
08930 
08931       /* Tell the CDR this DAHDI device hung up */
08932       ast_mutex_unlock(&p->lock);
08933       ast_channel_unlock(ast);
08934       ast_set_hangupsource(ast, name, 0);
08935       ast_channel_lock(ast);
08936       ast_mutex_lock(&p->lock);
08937    }
08938    return f;
08939 }

static int __unload_module ( void   )  [static]

Definition at line 16878 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(), destroy_all_channels(), sig_ss7_linkset::master, sig_pri_span::master, dahdi_pvt::next, dahdi_pvt::owner, sig_pri_stop_pri(), sig_pri_unload(), and SIG_SS7_NUM_DCHANS.

Referenced by load_module(), and unload_module().

16879 {
16880    struct dahdi_pvt *p;
16881 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16882    int i, j;
16883 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16884 
16885 #ifdef HAVE_PRI
16886    for (i = 0; i < NUM_SPANS; i++) {
16887       if (pris[i].pri.master != AST_PTHREADT_NULL) {
16888          pthread_cancel(pris[i].pri.master);
16889          pthread_kill(pris[i].pri.master, SIGURG);
16890       }
16891    }
16892    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16893    ast_unregister_application(dahdi_send_keypad_facility_app);
16894 #ifdef HAVE_PRI_PROG_W_CAUSE
16895    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16896 #endif
16897 #endif
16898 #if defined(HAVE_SS7)
16899    for (i = 0; i < NUM_SPANS; i++) {
16900       if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
16901          pthread_cancel(linksets[i].ss7.master);
16902          pthread_kill(linksets[i].ss7.master, SIGURG);
16903       }
16904    }
16905    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16906 #endif   /* defined(HAVE_SS7) */
16907 #if defined(HAVE_OPENR2)
16908    dahdi_r2_destroy_links();
16909    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16910    ast_unregister_application(dahdi_accept_r2_call_app);
16911 #endif
16912 
16913    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16914    ast_manager_unregister("DAHDIDialOffhook");
16915    ast_manager_unregister("DAHDIHangup");
16916    ast_manager_unregister("DAHDITransfer");
16917    ast_manager_unregister("DAHDIDNDoff");
16918    ast_manager_unregister("DAHDIDNDon");
16919    ast_manager_unregister("DAHDIShowChannels");
16920    ast_manager_unregister("DAHDIRestart");
16921    ast_data_unregister(NULL);
16922    ast_channel_unregister(&dahdi_tech);
16923 
16924    /* Hangup all interfaces if they have an owner */
16925    ast_mutex_lock(&iflock);
16926    for (p = iflist; p; p = p->next) {
16927       if (p->owner)
16928          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16929    }
16930    ast_mutex_unlock(&iflock);
16931 
16932    ast_mutex_lock(&monlock);
16933    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16934       pthread_cancel(monitor_thread);
16935       pthread_kill(monitor_thread, SIGURG);
16936       pthread_join(monitor_thread, NULL);
16937    }
16938    monitor_thread = AST_PTHREADT_STOP;
16939    ast_mutex_unlock(&monlock);
16940 
16941    destroy_all_channels();
16942 
16943 #if defined(HAVE_PRI)
16944    for (i = 0; i < NUM_SPANS; i++) {
16945       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
16946          pthread_join(pris[i].pri.master, NULL);
16947       }
16948       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16949          dahdi_close_pri_fd(&(pris[i]), j);
16950       }
16951       sig_pri_stop_pri(&pris[i].pri);
16952    }
16953 #if defined(HAVE_PRI_CCSS)
16954    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16955    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16956 #endif   /* defined(HAVE_PRI_CCSS) */
16957    sig_pri_unload();
16958 #endif
16959 
16960 #if defined(HAVE_SS7)
16961    for (i = 0; i < NUM_SPANS; i++) {
16962       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
16963          pthread_join(linksets[i].ss7.master, NULL);
16964       }
16965       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16966          dahdi_close_ss7_fd(&(linksets[i]), j);
16967       }
16968    }
16969 #endif   /* defined(HAVE_SS7) */
16970    ast_cond_destroy(&ss_thread_complete);
16971    return 0;
16972 }

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

References ast_log(), dahdi_pvt::channel, LOG_WARNING, dahdi_subchannel::owner, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.

03799 {
03800    int res;
03801    if (p->subs[SUB_REAL].owner == ast)
03802       res = 0;
03803    else if (p->subs[SUB_CALLWAIT].owner == ast)
03804       res = 1;
03805    else if (p->subs[SUB_THREEWAY].owner == ast)
03806       res = 2;
03807    else {
03808       res = -1;
03809       if (!nullok)
03810          ast_log(LOG_WARNING,
03811             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03812             ast ? ast->name : "", p->channel, fname, line);
03813    }
03814    return res;
03815 }

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

Definition at line 16193 of file chan_dahdi.c.

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

Referenced by load_module().

16194 {
16195    struct dahdi_pvt *p;
16196    const char *channel = astman_get_header(m, "DAHDIChannel");
16197    const char *number = astman_get_header(m, "Number");
16198    int i;
16199 
16200    if (ast_strlen_zero(channel)) {
16201       astman_send_error(s, m, "No channel specified");
16202       return 0;
16203    }
16204    if (ast_strlen_zero(number)) {
16205       astman_send_error(s, m, "No number specified");
16206       return 0;
16207    }
16208    p = find_channel_from_str(channel);
16209    if (!p) {
16210       astman_send_error(s, m, "No such channel");
16211       return 0;
16212    }
16213    if (!p->owner) {
16214       astman_send_error(s, m, "Channel does not have it's owner");
16215       return 0;
16216    }
16217    for (i = 0; i < strlen(number); i++) {
16218       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16219       dahdi_queue_frame(p, &f);
16220    }
16221    astman_send_ack(s, m, "DAHDIDialOffhook");
16222    return 0;
16223 }

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

Definition at line 16128 of file chan_dahdi.c.

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

Referenced by load_module().

16129 {
16130    struct dahdi_pvt *p;
16131    const char *channel = astman_get_header(m, "DAHDIChannel");
16132 
16133    if (ast_strlen_zero(channel)) {
16134       astman_send_error(s, m, "No channel specified");
16135       return 0;
16136    }
16137    p = find_channel_from_str(channel);
16138    if (!p) {
16139       astman_send_error(s, m, "No such channel");
16140       return 0;
16141    }
16142    dahdi_dnd(p, 0);
16143    astman_send_ack(s, m, "DND Disabled");
16144    return 0;
16145 }

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

Definition at line 16109 of file chan_dahdi.c.

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

Referenced by load_module().

16110 {
16111    struct dahdi_pvt *p;
16112    const char *channel = astman_get_header(m, "DAHDIChannel");
16113 
16114    if (ast_strlen_zero(channel)) {
16115       astman_send_error(s, m, "No channel specified");
16116       return 0;
16117    }
16118    p = find_channel_from_str(channel);
16119    if (!p) {
16120       astman_send_error(s, m, "No such channel");
16121       return 0;
16122    }
16123    dahdi_dnd(p, 1);
16124    astman_send_ack(s, m, "DND Enabled");
16125    return 0;
16126 }

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

Definition at line 15379 of file chan_dahdi.c.

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

Referenced by load_module().

15380 {
15381    if (dahdi_restart() != 0) {
15382       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15383       return 1;
15384    }
15385    astman_send_ack(s, m, "DAHDIRestart: Success");
15386    return 0;
15387 }

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

Definition at line 16225 of file chan_dahdi.c.

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

Referenced by load_module().

16226 {
16227    struct dahdi_pvt *tmp = NULL;
16228    const char *id = astman_get_header(m, "ActionID");
16229    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16230    char idText[256] = "";
16231    int channels = 0;
16232    int dahdichanquery;
16233 
16234    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16235       /* Not numeric string. */
16236       dahdichanquery = -1;
16237    }
16238 
16239    astman_send_ack(s, m, "DAHDI channel status will follow");
16240    if (!ast_strlen_zero(id))
16241       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16242 
16243    ast_mutex_lock(&iflock);
16244 
16245    for (tmp = iflist; tmp; tmp = tmp->next) {
16246       if (tmp->channel > 0) {
16247          int alm;
16248 
16249          /* If a specific channel is queried for, only deliver status for that channel */
16250          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16251             continue;
16252 
16253          alm = get_alarms(tmp);
16254          channels++;
16255          if (tmp->owner) {
16256             /* Add data if we have a current call */
16257             astman_append(s,
16258                "Event: DAHDIShowChannels\r\n"
16259                "DAHDIChannel: %d\r\n"
16260                "Channel: %s\r\n"
16261                "Uniqueid: %s\r\n"
16262                "AccountCode: %s\r\n"
16263                "Signalling: %s\r\n"
16264                "SignallingCode: %d\r\n"
16265                "Context: %s\r\n"
16266                "DND: %s\r\n"
16267                "Alarm: %s\r\n"
16268                "%s"
16269                "\r\n",
16270                tmp->channel,
16271                tmp->owner->name,
16272                tmp->owner->uniqueid,
16273                tmp->owner->accountcode,
16274                sig2str(tmp->sig),
16275                tmp->sig,
16276                tmp->context,
16277                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16278                alarm2str(alm), idText);
16279          } else {
16280             astman_append(s,
16281                "Event: DAHDIShowChannels\r\n"
16282                "DAHDIChannel: %d\r\n"
16283                "Signalling: %s\r\n"
16284                "SignallingCode: %d\r\n"
16285                "Context: %s\r\n"
16286                "DND: %s\r\n"
16287                "Alarm: %s\r\n"
16288                "%s"
16289                "\r\n",
16290                tmp->channel, sig2str(tmp->sig), tmp->sig,
16291                tmp->context,
16292                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16293                alarm2str(alm), idText);
16294          }
16295       }
16296    }
16297 
16298    ast_mutex_unlock(&iflock);
16299 
16300    astman_append(s,
16301       "Event: DAHDIShowChannelsComplete\r\n"
16302       "%s"
16303       "Items: %d\r\n"
16304       "\r\n",
16305       idText,
16306       channels);
16307    return 0;
16308 }

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

Definition at line 16147 of file chan_dahdi.c.

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

Referenced by load_module().

16148 {
16149    struct dahdi_pvt *p;
16150    const char *channel = astman_get_header(m, "DAHDIChannel");
16151 
16152    if (ast_strlen_zero(channel)) {
16153       astman_send_error(s, m, "No channel specified");
16154       return 0;
16155    }
16156    p = find_channel_from_str(channel);
16157    if (!p) {
16158       astman_send_error(s, m, "No such channel");
16159       return 0;
16160    }
16161    if (!analog_lib_handles(p->sig, 0, 0)) {
16162       astman_send_error(s, m, "Channel signaling is not analog");
16163       return 0;
16164    }
16165    dahdi_fake_event(p,TRANSFER);
16166    astman_send_ack(s, m, "DAHDITransfer");
16167    return 0;
16168 }

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

Definition at line 16170 of file chan_dahdi.c.

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

Referenced by load_module().

16171 {
16172    struct dahdi_pvt *p;
16173    const char *channel = astman_get_header(m, "DAHDIChannel");
16174 
16175    if (ast_strlen_zero(channel)) {
16176       astman_send_error(s, m, "No channel specified");
16177       return 0;
16178    }
16179    p = find_channel_from_str(channel);
16180    if (!p) {
16181       astman_send_error(s, m, "No such channel");
16182       return 0;
16183    }
16184    if (!analog_lib_handles(p->sig, 0, 0)) {
16185       astman_send_error(s, m, "Channel signaling is not analog");
16186       return 0;
16187    }
16188    dahdi_fake_event(p,HANGUP);
16189    astman_send_ack(s, m, "DAHDIHangup");
16190    return 0;
16191 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 4649 of file chan_dahdi.c.

References alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

04650 {
04651    int x;
04652    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04653       if (alarms[x].alarm & alm)
04654          return alarms[x].name;
04655    }
04656    return alm ? "Unknown Alarm" : "No Alarm";
04657 }

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

Definition at line 4450 of file chan_dahdi.c.

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

Referenced by analog_ss_thread(), dahdi_handle_event(), and my_allocate_sub().

04451 {
04452    struct dahdi_bufferinfo bi;
04453    int res;
04454    if (p->subs[x].dfd >= 0) {
04455       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04456       return -1;
04457    }
04458 
04459    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04460    if (p->subs[x].dfd <= -1) {
04461       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04462       return -1;
04463    }
04464 
04465    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04466    if (!res) {
04467       bi.txbufpolicy = p->buf_policy;
04468       bi.rxbufpolicy = p->buf_policy;
04469       bi.numbufs = p->buf_no;
04470       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04471       if (res < 0) {
04472          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04473       }
04474    } else
04475       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04476 
04477    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04478       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04479       dahdi_close_sub(p, x);
04480       p->subs[x].dfd = -1;
04481       return -1;
04482    }
04483    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04484    return 0;
04485 }

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

Definition at line 1578 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_fixup(), dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_request(), destroy_dahdi_pvt(), do_monitor(), mkintf(), mwi_thread(), and my_get_sigpvt_bridged_channel().

01579 {
01580    switch (signalling) {
01581    case SIG_FXOLS:
01582    case SIG_FXOGS:
01583    case SIG_FXOKS:
01584    case SIG_FXSLS:
01585    case SIG_FXSGS:
01586    case SIG_FXSKS:
01587    case SIG_EMWINK:
01588    case SIG_EM:
01589    case SIG_EM_E1:
01590    case SIG_FEATD:
01591    case SIG_FEATDMF:
01592    case SIG_E911:
01593    case SIG_FGC_CAMA:
01594    case SIG_FGC_CAMAMF:
01595    case SIG_FEATB:
01596    case SIG_SFWINK:
01597    case SIG_SF:
01598    case SIG_SF_FEATD:
01599    case SIG_SF_FEATDMF:
01600    case SIG_FEATDMF_TA:
01601    case SIG_SF_FEATB:
01602       break;
01603    default:
01604       /* The rest of the function should cover the remainder of signalling types */
01605       return 0;
01606    }
01607 
01608    if (radio) {
01609       return 0;
01610    }
01611 
01612    if (oprmode) {
01613       return 0;
01614    }
01615 
01616    return 1;
01617 }

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

Definition at line 9970 of file chan_dahdi.c.

References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), ast_clear_flag, ast_cond_signal, 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_remaining_ms(), ast_safe_sleep(), ast_set_callerid(), ast_set_flag, ast_setstate(), ast_shrink_phone_number(), ast_smdi_md_message_destroy(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_streamfile(), ast_strlen_zero(), ast_tvnow(), ast_verb, ast_waitfor(), ast_waitfordigit(), ast_waitstream(), ASTOBJ_UNREF, 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, CID_START_RING, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, dahdi_dnd(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index, dahdi_set_hook(), dahdi_setlinear(), dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), ast_channel::exten, ast_frame::frametype, ast_smdi_md_message::fwd_st, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, ast_party_caller::id, dahdi_pvt::immediate, dahdi_pvt::inalarm, ast_frame_subclass::integer, ISTRUNK, len(), dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, my_getsigstr(), my_handle_notify_message(), ast_party_id::name, name, NEED_MFDETECT, ast_party_id::number, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_COR, S_OR, 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_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, ast_party_number::str, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), dahdi_pvt::use_callerid, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, and ast_party_number::valid.

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

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

static int analog_tone_to_dahditone ( enum analog_tone  tone  )  [static]

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

01671 {
01672    switch (tone) {
01673    case ANALOG_TONE_RINGTONE:
01674       return DAHDI_TONE_RINGTONE;
01675    case ANALOG_TONE_STUTTER:
01676       return DAHDI_TONE_STUTTER;
01677    case ANALOG_TONE_CONGESTION:
01678       return DAHDI_TONE_CONGESTION;
01679    case ANALOG_TONE_DIALTONE:
01680       return DAHDI_TONE_DIALTONE;
01681    case ANALOG_TONE_DIALRECALL:
01682       return DAHDI_TONE_DIALRECALL;
01683    case ANALOG_TONE_INFO:
01684       return DAHDI_TONE_INFO;
01685    default:
01686       return -1;
01687    }
01688 }

static int analogsub_to_dahdisub ( enum analog_sub  analogsub  )  [static]

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

01691 {
01692    int index;
01693 
01694    switch (analogsub) {
01695    case ANALOG_SUB_REAL:
01696       index = SUB_REAL;
01697       break;
01698    case ANALOG_SUB_CALLWAIT:
01699       index = SUB_CALLWAIT;
01700       break;
01701    case ANALOG_SUB_THREEWAY:
01702       index = SUB_THREEWAY;
01703       break;
01704    default:
01705       ast_log(LOG_ERROR, "Unidentified sub!\n");
01706       index = SUB_REAL;
01707    }
01708 
01709    return index;
01710 }

AST_DATA_STRUCTURE ( dahdi_pvt  ,
DATA_EXPORT_DAHDI_PVT   
)
AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_LOAD_ORDER  ,
tdesc  ,
load = load_module,
unload = unload_module,
reload = reload,
load_pri = AST_MODPRI_CHANNEL_DRIVER,
nonoptreq = "res_smdi" 
)
AST_MUTEX_DEFINE_STATIC ( restart_lock   ) 
AST_MUTEX_DEFINE_STATIC ( ss_thread_lock   ) 
AST_MUTEX_DEFINE_STATIC ( monlock   ) 

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

AST_MUTEX_DEFINE_STATIC ( iflock   ) 

Protect the interface list (of dahdi_pvt's).

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

Definition at line 7685 of file chan_dahdi.c.

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

Referenced by dahdi_handle_event().

07686 {
07687    /* In order to transfer, we need at least one of the channels to
07688       actually be in a call bridge.  We can't conference two applications
07689       together (but then, why would we want to?) */
07690    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07691       /* The three-way person we're about to transfer to could still be in MOH, so
07692          stop if now if appropriate */
07693       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07694          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07695       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07696          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07697       }
07698       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07699          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07700       }
07701        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07702          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07703                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07704          return -1;
07705       }
07706       /* Orphan the channel after releasing the lock */
07707       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07708       unalloc_sub(p, SUB_THREEWAY);
07709    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07710       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07711       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07712          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07713       }
07714       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07715          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07716       }
07717       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07718          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07719                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07720          return -1;
07721       }
07722       /* Three-way is now the REAL */
07723       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07724       ast_channel_unlock(p->subs[SUB_REAL].owner);
07725       unalloc_sub(p, SUB_THREEWAY);
07726       /* Tell the caller not to hangup */
07727       return 1;
07728    } else {
07729       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07730          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07731       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07732       return -1;
07733    }
07734    return 0;
07735 }

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

Definition at line 13288 of file chan_dahdi.c.

References analog_available(), analog_lib_handles(), sig_pri_chan::chan_pvt, dahdi_pvt::inalarm, dahdi_pvt::locallyblocked, 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(), and dahdi_request().

13289 {
13290    struct dahdi_pvt *p = *pvt;
13291 
13292    if (p->inalarm)
13293       return 0;
13294 
13295    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13296       return analog_available(p->sig_pvt);
13297 
13298    switch (p->sig) {
13299 #if defined(HAVE_PRI)
13300    case SIG_PRI_LIB_HANDLE_CASES:
13301       {
13302          struct sig_pri_chan *pvt_chan;
13303          int res;
13304 
13305          pvt_chan = p->sig_pvt;
13306          res = sig_pri_available(&pvt_chan, is_specific_channel);
13307          *pvt = pvt_chan->chan_pvt;
13308          return res;
13309       }
13310 #endif   /* defined(HAVE_PRI) */
13311 #if defined(HAVE_SS7)
13312    case SIG_SS7:
13313       return sig_ss7_available(p->sig_pvt);
13314 #endif   /* defined(HAVE_SS7) */
13315    default:
13316       break;
13317    }
13318 
13319    if (p->locallyblocked || p->remotelyblocked) {
13320       return 0;
13321    }
13322 
13323    /* If no owner definitely available */
13324    if (!p->owner) {
13325 #ifdef HAVE_OPENR2
13326       /* Trust MFC/R2 */
13327       if (p->mfcr2) {
13328          if (p->mfcr2call) {
13329             return 0;
13330          } else {
13331             return 1;
13332          }
13333       }
13334 #endif
13335       return 1;
13336    }
13337 
13338    return 0;
13339 }

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

Definition at line 17013 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, LOG_ERROR, LOG_WARNING, mkintf(), parse_spanchan(), dahdi_pvt::sig, and sig2str.

Referenced by process_dahdi().

17014 {
17015    char *c, *chan;
17016    char *subdir;
17017    int x, start, finish;
17018    struct dahdi_pvt *tmp;
17019 
17020    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17021       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17022       return -1;
17023    }
17024 
17025    c = ast_strdupa(value);
17026    c = parse_spanchan(c, &subdir);
17027 
17028    while ((chan = strsep(&c, ","))) {
17029       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
17030          /* Range */
17031       } else if (sscanf(chan, "%30d", &start)) {
17032          /* Just one */
17033          finish = start;
17034       } else if (!strcasecmp(chan, "pseudo")) {
17035          finish = start = CHAN_PSEUDO;
17036          if (found_pseudo)
17037             *found_pseudo = 1;
17038       } else {
17039          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
17040          return -1;
17041       }
17042       if (finish < start) {
17043          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
17044          x = finish;
17045          finish = start;
17046          start = x;
17047       }
17048 
17049       for (x = start; x <= finish; x++) {
17050          char fn[PATH_MAX];
17051          int real_channel = x;
17052 
17053          if (!ast_strlen_zero(subdir)) {
17054             real_channel = device2chan(subdir, x, fn, sizeof(fn));
17055             if (real_channel < 0) {
17056                if (conf->ignore_failed_channels) {
17057                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
17058                         subdir, x, real_channel);
17059                   continue;
17060                } else {
17061                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
17062                         subdir, x, real_channel);
17063                   return -1;
17064                }
17065             }
17066          }
17067          tmp = mkintf(real_channel, conf, reload);
17068 
17069          if (tmp) {
17070             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
17071          } else {
17072             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17073                   (reload == 1) ? "reconfigure" : "register", value);
17074             return -1;
17075          }
17076       }
17077    }
17078 
17079    return 0;
17080 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

Definition at line 5164 of file chan_dahdi.c.

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

05165 {
05166    int res;
05167 
05168    /* Bump receive gain by value stored in cid_rxgain */
05169    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05170    if (res) {
05171       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05172       return -1;
05173    }
05174 
05175    return 0;
05176 }

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

Definition at line 11121 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by do_monitor(), and mwi_thread().

11122 {
11123    int x;
11124    int sum = 0;
11125 
11126    if (!len)
11127       return 0;
11128 
11129    for (x = 0; x < len; x++)
11130       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11131 
11132    return sum / len;
11133 }

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

Definition at line 9943 of file chan_dahdi.c.

References ast_pickup_ext(), and pickup_ext.

Referenced by analog_ss_thread().

09944 {
09945    int extlen = strlen(exten);
09946    const char *pickup_ext;
09947    if (!extlen) {
09948       return 1;
09949    }
09950    pickup_ext = ast_pickup_ext();
09951    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09952       return 1;
09953    }
09954    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09955    if (exten[0] == '*' && extlen < 3) {
09956       if (extlen == 1) {
09957          return 1;
09958       }
09959       /* "*0" should be processed before it gets here */
09960       switch (exten[1]) {
09961       case '6':
09962       case '7':
09963       case '8':
09964          return 1;
09965       }
09966    }
09967    return 0;
09968 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

Definition at line 7737 of file chan_dahdi.c.

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

Referenced by dahdi_handle_event(), and my_check_for_conference().

07738 {
07739    struct dahdi_confinfo ci;
07740    /* Fine if we already have a master, etc */
07741    if (p->master || (p->confno > -1))
07742       return 0;
07743    memset(&ci, 0, sizeof(ci));
07744    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07745       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07746       return 0;
07747    }
07748    /* If we have no master and don't have a confno, then
07749       if we're in a conference, it's probably a MeetMe room or
07750       some such, so don't let us 3-way out! */
07751    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07752       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07753       return 1;
07754    }
07755    return 0;
07756 }

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

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

04735 {
04736    /* If the conference already exists, and we're already in it
04737       don't bother doing anything */
04738    struct dahdi_confinfo zi;
04739 
04740    memset(&zi, 0, sizeof(zi));
04741    zi.chan = 0;
04742 
04743    if (slavechannel > 0) {
04744       /* If we have only one slave, do a digital mon */
04745       zi.confmode = DAHDI_CONF_DIGITALMON;
04746       zi.confno = slavechannel;
04747    } else {
04748       if (!idx) {
04749          /* Real-side and pseudo-side both participate in conference */
04750          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04751             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04752       } else
04753          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04754       zi.confno = p->confno;
04755    }
04756    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04757       return 0;
04758    if (c->dfd < 0)
04759       return 0;
04760    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04761       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04762       return -1;
04763    }
04764    if (slavechannel < 1) {
04765       p->confno = zi.confno;
04766    }
04767    c->curconf = zi;
04768    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04769    return 0;
04770 }

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

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

04784 {
04785    struct dahdi_confinfo zi;
04786    if (/* Can't delete if there's no dfd */
04787       (c->dfd < 0) ||
04788       /* Don't delete from the conference if it's not our conference */
04789       !isourconf(p, c)
04790       /* Don't delete if we don't think it's conferenced at all (implied) */
04791       ) return 0;
04792    memset(&zi, 0, sizeof(zi));
04793    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04794       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04795       return -1;
04796    }
04797    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04798    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04799    return 0;
04800 }

static struct ast_str* create_channel_name ( struct dahdi_pvt i  )  [static, read]

Definition at line 9603 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(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::lock, dahdi_subchannel::owner, dahdi_pvt::span, and dahdi_pvt::subs.

Referenced by dahdi_cc_callback(), and dahdi_new().

09605 {
09606    struct ast_str *chan_name;
09607    int x, y;
09608 
09609    /* Create the new channel name tail. */
09610    if (!(chan_name = ast_str_create(32))) {
09611       return NULL;
09612    }
09613    if (i->channel == CHAN_PSEUDO) {
09614       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09615 #if defined(HAVE_PRI)
09616    } else if (i->pri) {
09617       ast_mutex_lock(&i->pri->lock);
09618       y = ++i->pri->new_chan_seq;
09619       if (is_outgoing) {
09620          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
09621          address[0] = '\0';
09622       } else if (ast_strlen_zero(i->cid_subaddr)) {
09623          /* Put in caller-id number only since there is no subaddress. */
09624          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
09625       } else {
09626          /* Put in caller-id number and subaddress. */
09627          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09628             i->cid_subaddr, (unsigned)y);
09629       }
09630       ast_mutex_unlock(&i->pri->lock);
09631 #endif   /* defined(HAVE_PRI) */
09632    } else {
09633       y = 1;
09634       do {
09635          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09636          for (x = 0; x < 3; ++x) {
09637             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09638                i->subs[x].owner->name + 6)) {
09639                break;
09640             }
09641          }
09642          ++y;
09643       } while (x < 3);
09644    }
09645    return chan_name;
09646 }

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

Definition at line 2186 of file chan_dahdi.c.

References ast_manager_event, CHAN_PSEUDO, dahdi_pvt::channel, EVENT_FLAG_CALL, and dahdi_pvt::span.

Referenced by dahdi_new().

02187 {
02188    char ch_name[20];
02189 
02190    if (p->channel < CHAN_PSEUDO) {
02191       /* No B channel */
02192       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02193    } else if (p->channel == CHAN_PSEUDO) {
02194       /* Pseudo channel */
02195       strcpy(ch_name, "pseudo");
02196    } else {
02197       /* Real channel */
02198       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02199    }
02200    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02201       "Channel: %s\r\n"
02202       "Uniqueid: %s\r\n"
02203       "DAHDISpan: %d\r\n"
02204       "DAHDIChannel: %s\r\n",
02205       chan->name,
02206       chan->uniqueid,
02207       p->span,
02208       ch_name);
02209 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

Todo:
XXX this is redundantly set by the analog and PRI submodules!

Definition at line 6613 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_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::oprmode, 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.

06614 {
06615    struct dahdi_pvt *p = ast->tech_pvt;
06616    int res = 0;
06617    int idx;
06618    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06619    ast_mutex_lock(&p->lock);
06620    idx = dahdi_get_index(ast, p, 0);
06621    if (idx < 0)
06622       idx = SUB_REAL;
06623    /* nothing to do if a radio channel */
06624    if ((p->radio || (p->oprmode < 0))) {
06625       ast_mutex_unlock(&p->lock);
06626       return 0;
06627    }
06628 
06629    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06630       res = analog_answer(p->sig_pvt, ast);
06631       ast_mutex_unlock(&p->lock);
06632       return res;
06633    }
06634 
06635    switch (p->sig) {
06636 #if defined(HAVE_PRI)
06637    case SIG_PRI_LIB_HANDLE_CASES:
06638       res = sig_pri_answer(p->sig_pvt, ast);
06639       break;
06640 #endif   /* defined(HAVE_PRI) */
06641 #if defined(HAVE_SS7)
06642    case SIG_SS7:
06643       res = sig_ss7_answer(p->sig_pvt, ast);
06644       break;
06645 #endif   /* defined(HAVE_SS7) */
06646 #ifdef HAVE_OPENR2
06647    case SIG_MFCR2:
06648       if (!p->mfcr2_call_accepted) {
06649          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06650             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06651          p->mfcr2_answer_pending = 1;
06652          if (p->mfcr2_charge_calls) {
06653             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06654             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06655          } else {
06656             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06657             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06658          }
06659       } else {
06660          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06661          dahdi_r2_answer(p);
06662       }
06663       break;
06664 #endif
06665    case 0:
06666       ast_mutex_unlock(&p->lock);
06667       return 0;
06668    default:
06669       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06670       res = -1;
06671       break;
06672    }
06673    ast_mutex_unlock(&p->lock);
06674    return res;
06675 }

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

07261 {
07262    struct ast_channel *who;
07263    struct dahdi_pvt *p0, *p1, *op0, *op1;
07264    struct dahdi_pvt *master = NULL, *slave = NULL;
07265    struct ast_frame *f;
07266    int inconf = 0;
07267    int nothingok = 1;
07268    int ofd0, ofd1;
07269    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07270    int os0 = -1, os1 = -1;
07271    int priority = 0;
07272    struct ast_channel *oc0, *oc1;
07273    enum ast_bridge_result res;
07274    struct timeval start = ast_tvnow();
07275 #ifdef PRI_2BCT
07276    int triedtopribridge = 0;
07277    q931_call *q931c0;
07278    q931_call *q931c1;
07279 #endif
07280 
07281    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07282       There is code below to handle it properly until DTMF is actually seen,
07283       but due to currently unresolved issues it's ignored...
07284    */
07285 
07286    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07287       return AST_BRIDGE_FAILED_NOWARN;
07288 
07289    ast_channel_lock(c0);
07290    while (ast_channel_trylock(c1)) {
07291       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07292    }
07293 
07294    p0 = c0->tech_pvt;
07295    p1 = c1->tech_pvt;
07296    /* cant do pseudo-channels here */
07297    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07298       ast_channel_unlock(c0);
07299       ast_channel_unlock(c1);
07300       return AST_BRIDGE_FAILED_NOWARN;
07301    }
07302 
07303    oi0 = dahdi_get_index(c0, p0, 0);
07304    oi1 = dahdi_get_index(c1, p1, 0);
07305    if ((oi0 < 0) || (oi1 < 0)) {
07306       ast_channel_unlock(c0);
07307       ast_channel_unlock(c1);
07308       return AST_BRIDGE_FAILED;
07309    }
07310 
07311    op0 = p0 = c0->tech_pvt;
07312    op1 = p1 = c1->tech_pvt;
07313    ofd0 = c0->fds[0];
07314    ofd1 = c1->fds[0];
07315    oc0 = p0->owner;
07316    oc1 = p1->owner;
07317 
07318    if (ast_mutex_trylock(&p0->lock)) {
07319       /* Don't block, due to potential for deadlock */
07320       ast_channel_unlock(c0);
07321       ast_channel_unlock(c1);
07322       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07323       return AST_BRIDGE_RETRY;
07324    }
07325    if (ast_mutex_trylock(&p1->lock)) {
07326       /* Don't block, due to potential for deadlock */
07327       ast_mutex_unlock(&p0->lock);
07328       ast_channel_unlock(c0);
07329       ast_channel_unlock(c1);
07330       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07331       return AST_BRIDGE_RETRY;
07332    }
07333 
07334    if ((p0->callwaiting && p0->callwaitingcallerid)
07335       || (p1->callwaiting && p1->callwaitingcallerid)) {
07336       /*
07337        * Call Waiting Caller ID requires DTMF detection to know if it
07338        * can send the CID spill.
07339        *
07340        * For now, don't attempt to native bridge if either channel
07341        * needs DTMF detection.  There is code below to handle it
07342        * properly until DTMF is actually seen, but due to currently
07343        * unresolved issues it's ignored...
07344        */
07345       ast_mutex_unlock(&p0->lock);
07346       ast_mutex_unlock(&p1->lock);
07347       ast_channel_unlock(c0);
07348       ast_channel_unlock(c1);
07349       return AST_BRIDGE_FAILED_NOWARN;
07350    }
07351 
07352 #if defined(HAVE_PRI)
07353    if ((dahdi_sig_pri_lib_handles(p0->sig)
07354          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07355       || (dahdi_sig_pri_lib_handles(p1->sig)
07356          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07357       /*
07358        * PRI nobch channels (hold and call waiting) are equivalent to
07359        * pseudo channels and cannot be done here.
07360        */
07361       ast_mutex_unlock(&p0->lock);
07362       ast_mutex_unlock(&p1->lock);
07363       ast_channel_unlock(c0);
07364       ast_channel_unlock(c1);
07365       return AST_BRIDGE_FAILED_NOWARN;
07366    }
07367 #endif   /* defined(HAVE_PRI) */
07368 
07369    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07370       if (p0->owner && p1->owner) {
07371          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07372          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07373             master = p0;
07374             slave = p1;
07375             inconf = 1;
07376          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07377             master = p1;
07378             slave = p0;
07379             inconf = 1;
07380          } else {
07381             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07382             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07383                p0->channel,
07384                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07385                p0->subs[SUB_REAL].inthreeway, p0->channel,
07386                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07387                p1->subs[SUB_REAL].inthreeway);
07388          }
07389          nothingok = 0;
07390       }
07391    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07392       if (p1->subs[SUB_THREEWAY].inthreeway) {
07393          master = p1;
07394          slave = p0;
07395          nothingok = 0;
07396       }
07397    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07398       if (p0->subs[SUB_THREEWAY].inthreeway) {
07399          master = p0;
07400          slave = p1;
07401          nothingok = 0;
07402       }
07403    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07404       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07405          don't put us in anything */
07406       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07407          master = p1;
07408          slave = p0;
07409          nothingok = 0;
07410       }
07411    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07412       /* Same as previous */
07413       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07414          master = p0;
07415          slave = p1;
07416          nothingok = 0;
07417       }
07418    }
07419    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07420       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07421    if (master && slave) {
07422       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07423          in an active threeway call with a channel that is ringing, we should
07424          indicate ringing. */
07425       if ((oi1 == SUB_THREEWAY) &&
07426          p1->subs[SUB_THREEWAY].inthreeway &&
07427          p1->subs[SUB_REAL].owner &&
07428          p1->subs[SUB_REAL].inthreeway &&
07429          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07430          ast_debug(1,
07431             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07432             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07433          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07434          os1 = p1->subs[SUB_REAL].owner->_state;
07435       } else {
07436          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07437             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07438          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07439       }
07440       if ((oi0 == SUB_THREEWAY) &&
07441          p0->subs[SUB_THREEWAY].inthreeway &&
07442          p0->subs[SUB_REAL].owner &&
07443          p0->subs[SUB_REAL].inthreeway &&
07444          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07445          ast_debug(1,
07446             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07447             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07448          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07449          os0 = p0->subs[SUB_REAL].owner->_state;
07450       } else {
07451          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07452             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07453          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07454       }
07455       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07456          if (!p0->echocanbridged || !p1->echocanbridged) {
07457             /* Disable echo cancellation if appropriate */
07458             dahdi_disable_ec(p0);
07459             dahdi_disable_ec(p1);
07460          }
07461       }
07462       dahdi_link(slave, master);
07463       master->inconference = inconf;
07464    } else if (!nothingok)
07465       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07466 
07467    update_conf(p0);
07468    update_conf(p1);
07469    t0 = p0->subs[SUB_REAL].inthreeway;
07470    t1 = p1->subs[SUB_REAL].inthreeway;
07471 
07472    ast_mutex_unlock(&p0->lock);
07473    ast_mutex_unlock(&p1->lock);
07474 
07475    ast_channel_unlock(c0);
07476    ast_channel_unlock(c1);
07477 
07478    /* Native bridge failed */
07479    if ((!master || !slave) && !nothingok) {
07480       dahdi_enable_ec(p0);
07481       dahdi_enable_ec(p1);
07482       return AST_BRIDGE_FAILED;
07483    }
07484 
07485    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07486 
07487    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07488       disable_dtmf_detect(op0);
07489 
07490    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07491       disable_dtmf_detect(op1);
07492 
07493    for (;;) {
07494       struct ast_channel *c0_priority[2] = {c0, c1};
07495       struct ast_channel *c1_priority[2] = {c1, c0};
07496       int ms;
07497 
07498       /* Here's our main loop...  Start by locking things, looking for private parts,
07499          and then balking if anything is wrong */
07500 
07501       ast_channel_lock(c0);
07502       while (ast_channel_trylock(c1)) {
07503          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07504       }
07505 
07506       p0 = c0->tech_pvt;
07507       p1 = c1->tech_pvt;
07508 
07509       if (op0 == p0)
07510          i0 = dahdi_get_index(c0, p0, 1);
07511       if (op1 == p1)
07512          i1 = dahdi_get_index(c1, p1, 1);
07513 
07514       ast_channel_unlock(c0);
07515       ast_channel_unlock(c1);
07516       ms = ast_remaining_ms(start, timeoutms);
07517       if (!ms ||
07518          (op0 != p0) ||
07519          (op1 != p1) ||
07520          (ofd0 != c0->fds[0]) ||
07521          (ofd1 != c1->fds[0]) ||
07522          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07523          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07524          (oc0 != p0->owner) ||
07525          (oc1 != p1->owner) ||
07526          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07527          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07528          (oi0 != i0) ||
07529          (oi1 != i1)) {
07530          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07531             op0->channel, oi0, op1->channel, oi1);
07532          res = AST_BRIDGE_RETRY;
07533          goto return_from_bridge;
07534       }
07535 
07536 #ifdef PRI_2BCT
07537       if (!triedtopribridge) {
07538          triedtopribridge = 1;
07539          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07540             ast_mutex_lock(&p0->pri->lock);
07541             switch (p0->sig) {
07542             case SIG_PRI_LIB_HANDLE_CASES:
07543                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07544                break;
07545             default:
07546                q931c0 = NULL;
07547                break;
07548             }
07549             switch (p1->sig) {
07550             case SIG_PRI_LIB_HANDLE_CASES:
07551                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07552                break;
07553             default:
07554                q931c1 = NULL;
07555                break;
07556             }
07557             if (q931c0 && q931c1) {
07558                pri_channel_bridge(q931c0, q931c1);
07559             }
07560             ast_mutex_unlock(&p0->pri->lock);
07561          }
07562       }
07563 #endif
07564 
07565       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07566       if (!who) {
07567          ast_debug(1, "Ooh, empty read...\n");
07568          continue;
07569       }
07570       f = ast_read(who);
07571       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07572          *fo = f;
07573          *rc = who;
07574          res = AST_BRIDGE_COMPLETE;
07575          goto return_from_bridge;
07576       }
07577       if (f->frametype == AST_FRAME_DTMF) {
07578          if ((who == c0) && p0->pulsedial) {
07579             ast_write(c1, f);
07580          } else if ((who == c1) && p1->pulsedial) {
07581             ast_write(c0, f);
07582          } else {
07583             *fo = f;
07584             *rc = who;
07585             res = AST_BRIDGE_COMPLETE;
07586             goto return_from_bridge;
07587          }
07588       }
07589       ast_frfree(f);
07590 
07591       /* Swap who gets priority */
07592       priority = !priority;
07593    }
07594 
07595 return_from_bridge:
07596    if (op0 == p0)
07597       dahdi_enable_ec(p0);
07598 
07599    if (op1 == p1)
07600       dahdi_enable_ec(p1);
07601 
07602    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07603       enable_dtmf_detect(op0);
07604 
07605    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07606       enable_dtmf_detect(op1);
07607 
07608    dahdi_unlink(slave, master, 1);
07609 
07610    return res;
07611 }

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

Definition at line 5398 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_sig_pri_lib_handles(), dahdi_subchannel::dfd, 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_subchannel::needbusy, ast_party_id::number, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, 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.

05399 {
05400    struct dahdi_pvt *p = ast->tech_pvt;
05401    int x, res, mysig;
05402    char dest[256]; /* must be same length as p->dialdest */
05403 
05404    ast_mutex_lock(&p->lock);
05405    ast_copy_string(dest, rdest, sizeof(dest));
05406    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05407    if ((ast->_state == AST_STATE_BUSY)) {
05408       p->subs[SUB_REAL].needbusy = 1;
05409       ast_mutex_unlock(&p->lock);
05410       return 0;
05411    }
05412    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05413       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05414       ast_mutex_unlock(&p->lock);
05415       return -1;
05416    }
05417    p->waitingfordt.tv_sec = 0;
05418    p->dialednone = 0;
05419    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05420    {
05421       /* Special pseudo -- automatically up */
05422       ast_setstate(ast, AST_STATE_UP);
05423       ast_mutex_unlock(&p->lock);
05424       return 0;
05425    }
05426    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05427    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05428    if (res)
05429       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05430    p->outgoing = 1;
05431 
05432    if (IS_DIGITAL(ast->transfercapability)){
05433       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05434    } else {
05435       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05436    }  
05437 
05438 #ifdef HAVE_PRI
05439    if (dahdi_sig_pri_lib_handles(p->sig)) {
05440       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05441          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05442       ast_mutex_unlock(&p->lock);
05443       return res;
05444    }
05445 #endif
05446 
05447 #if defined(HAVE_SS7)
05448    if (p->sig == SIG_SS7) {
05449       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05450       ast_mutex_unlock(&p->lock);
05451       return res;
05452    }
05453 #endif   /* defined(HAVE_SS7) */
05454 
05455    /* If this is analog signalling we can exit here */
05456    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05457       p->callwaitrings = 0;
05458       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05459       ast_mutex_unlock(&p->lock);
05460       return res;
05461    }
05462 
05463    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05464    switch (mysig) {
05465    case 0:
05466       /* Special pseudo -- automatically up*/
05467       ast_setstate(ast, AST_STATE_UP);
05468       break;
05469    case SIG_MFCR2:
05470       break;
05471    default:
05472       ast_debug(1, "not yet implemented\n");
05473       ast_mutex_unlock(&p->lock);
05474       return -1;
05475    }
05476 
05477 #ifdef HAVE_OPENR2
05478    if (p->mfcr2) {
05479       openr2_calling_party_category_t chancat;
05480       int callres = 0;
05481       char *c, *l;
05482 
05483       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05484       p->dialdest[0] = '\0';
05485 
05486       c = strchr(dest, '/');
05487       if (c) {
05488          c++;
05489       } else {
05490          c = "";
05491       }
05492       if (!p->hidecallerid) {
05493          l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05494       } else {
05495          l = NULL;
05496       }
05497       if (strlen(c) < p->stripmsd) {
05498          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05499          ast_mutex_unlock(&p->lock);
05500          return -1;
05501       }
05502       p->dialing = 1;
05503       chancat = dahdi_r2_get_channel_category(ast);
05504       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05505       if (-1 == callres) {
05506          ast_mutex_unlock(&p->lock);
05507          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05508          return -1;
05509       }
05510       p->mfcr2_call_accepted = 0;
05511       p->mfcr2_progress = 0;
05512       ast_setstate(ast, AST_STATE_DIALING);
05513    }
05514 #endif /* HAVE_OPENR2 */
05515    ast_mutex_unlock(&p->lock);
05516    return 0;
05517 }

static int dahdi_callwait ( struct ast_channel ast  )  [static]

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

05366 {
05367    struct dahdi_pvt *p = ast->tech_pvt;
05368    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05369    if (p->cidspill) {
05370       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05371       ast_free(p->cidspill);
05372    }
05373 
05374    /*
05375     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05376     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05377     */
05378    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05379       return -1;
05380    save_conference(p);
05381    /* Silence */
05382    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05383    if (!p->callwaitrings && p->callwaitingcallerid) {
05384       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05385       p->callwaitcas = 1;
05386       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05387    } else {
05388       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05389       p->callwaitcas = 0;
05390       p->cidlen = 2400 + READ_SIZE * 4;
05391    }
05392    p->cidpos = 0;
05393    send_callerid(p);
05394 
05395    return 0;
05396 }

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 13953 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_starting_point::backwards, dahdi_pvt::cc_params, dahdi_starting_point::channelmatch, create_channel_name(), dahdi_sig_pri_lib_handles(), determine_starting_point(), dahdi_starting_point::groupmatch, HAVE_PRI, is_group_or_channel_match(), dahdi_pvt::next, dahdi_pvt::prev, dahdi_pvt::sig, dahdi_pvt::span, and dahdi_starting_point::span.

13954 {
13955    struct dahdi_pvt *p;
13956    struct dahdi_pvt *exitpvt;
13957    struct dahdi_starting_point start;
13958    int groupmatched = 0;
13959    int channelmatched = 0;
13960 
13961    ast_mutex_lock(&iflock);
13962    p = determine_starting_point(dest, &start);
13963    if (!p) {
13964       ast_mutex_unlock(&iflock);
13965       return -1;
13966    }
13967    exitpvt = p;
13968    for (;;) {
13969       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13970          /* We found a potential match. call the callback */
13971          struct ast_str *device_name;
13972          char *dash;
13973          const char *monitor_type;
13974          char dialstring[AST_CHANNEL_NAME];
13975          char full_device_name[AST_CHANNEL_NAME];
13976 
13977          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13978          case AST_CC_MONITOR_NEVER:
13979             break;
13980          case AST_CC_MONITOR_NATIVE:
13981          case AST_CC_MONITOR_ALWAYS:
13982          case AST_CC_MONITOR_GENERIC:
13983 #if defined(HAVE_PRI)
13984             if (dahdi_sig_pri_lib_handles(p->sig)) {
13985                /*
13986                 * ISDN is in a trunk busy condition so we need to monitor
13987                 * the span congestion device state.
13988                 */
13989                snprintf(full_device_name, sizeof(full_device_name),
13990                   "DAHDI/I%d/congestion", p->pri->span);
13991             } else
13992 #endif   /* defined(HAVE_PRI) */
13993             {
13994 #if defined(HAVE_PRI)
13995                device_name = create_channel_name(p, 1, "");
13996 #else
13997                device_name = create_channel_name(p);
13998 #endif   /* defined(HAVE_PRI) */
13999                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14000                   device_name ? ast_str_buffer(device_name) : "");
14001                ast_free(device_name);
14002                /*
14003                 * The portion after the '-' in the channel name is either a random
14004                 * number, a sequence number, or a subchannel number. None are
14005                 * necessary so strip them off.
14006                 */
14007                dash = strrchr(full_device_name, '-');
14008                if (dash) {
14009                   *dash = '\0';
14010                }
14011             }
14012             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14013 
14014             /*
14015              * Analog can only do generic monitoring.
14016              * ISDN is in a trunk busy condition and any "device" is going
14017              * to be busy until a B channel becomes available.  The generic
14018              * monitor can do this task.
14019              */
14020             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14021             callback(inbound,
14022 #if defined(HAVE_PRI)
14023                p->pri ? p->pri->cc_params : p->cc_params,
14024 #else
14025                p->cc_params,
14026 #endif   /* defined(HAVE_PRI) */
14027                monitor_type, full_device_name, dialstring, NULL);
14028             break;
14029          }
14030       }
14031       p = start.backwards ? p->prev : p->next;
14032       if (!p) {
14033          p = start.backwards ? ifend : iflist;
14034       }
14035       if (p == exitpvt) {
14036          break;
14037       }
14038    }
14039    ast_mutex_unlock(&iflock);
14040    return 0;
14041 }

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

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

Definition at line 1370 of file chan_dahdi.c.

References ast_cc_config_params_init, CID_SIG_BELL, CID_START_RING, DAHDI_CHAN_MAPPING_PHYSICAL, and DEFAULT_CIDRINGS.

Referenced by process_dahdi(), and setup_dahdi().

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

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

Definition at line 18677 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, and dahdi_pvt::next.

18679 {
18680    struct dahdi_pvt *tmp;
18681    struct ast_data *data_channel;
18682 
18683    ast_mutex_lock(&iflock);
18684    for (tmp = iflist; tmp; tmp = tmp->next) {
18685       data_channel = ast_data_add_node(data_root, "channel");
18686       if (!data_channel) {
18687          continue;
18688       }
18689 
18690       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18691 
18692       /* if this channel doesn't match remove it. */
18693       if (!ast_data_search_match(search, data_channel)) {
18694          ast_data_remove_node(data_root, data_channel);
18695       }
18696    }
18697    ast_mutex_unlock(&iflock);
18698 
18699    return 0;
18700 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 4416 of file chan_dahdi.c.

Referenced by dahdi_close_sub().

04417 {
04418    if (fd > 0)
04419       close(fd);
04420 }

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

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

04423 {
04424    dahdi_close(chan_pvt->subs[sub_num].dfd);
04425    chan_pvt->subs[sub_num].dfd = -1;
04426 }

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

Definition at line 5208 of file chan_dahdi.c.

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

05209 {
05210    int x, res;
05211 
05212    x = muted;
05213 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05214    switch (p->sig) {
05215 #if defined(HAVE_PRI)
05216    case SIG_PRI_LIB_HANDLE_CASES:
05217       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05218          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05219          break;
05220       }
05221       /* Fall through */
05222 #endif   /* defined(HAVE_PRI) */
05223 #if defined(HAVE_SS7)
05224    case SIG_SS7:
05225 #endif   /* defined(HAVE_SS7) */
05226       {
05227          int y = 1;
05228 
05229          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05230          if (res)
05231             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05232                p->channel, strerror(errno));
05233       }
05234       break;
05235    default:
05236       break;
05237    }
05238 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05239    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05240    if (res < 0)
05241       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05242    return res;
05243 }

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

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

15194 {
15195    int channel;
15196    int ret;
15197    switch (cmd) {
15198    case CLI_INIT:
15199       e->command = "dahdi destroy channel";
15200       e->usage =
15201          "Usage: dahdi destroy channel <chan num>\n"
15202          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15203       return NULL;
15204    case CLI_GENERATE:
15205       return NULL;
15206    }
15207    if (a->argc != 4)
15208       return CLI_SHOWUSAGE;
15209 
15210    channel = atoi(a->argv[3]);
15211    ret = dahdi_destroy_channel_bynum(channel);
15212    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15213 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

Definition at line 11471 of file chan_dahdi.c.

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

Referenced by dahdi_destroy_channel(), and do_monitor().

11472 {
11473    struct dahdi_pvt *cur;
11474 
11475    ast_mutex_lock(&iflock);
11476    for (cur = iflist; cur; cur = cur->next) {
11477       if (cur->channel == channel) {
11478          int x = DAHDI_FLASH;
11479 
11480          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11481          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11482 
11483          destroy_channel(cur, 1);
11484          ast_mutex_unlock(&iflock);
11485          ast_module_unref(ast_module_info->self);
11486          return RESULT_SUCCESS;
11487       }
11488    }
11489    ast_mutex_unlock(&iflock);
11490    return RESULT_FAILURE;
11491 }

static int dahdi_devicestate ( void *  data  )  [static]

Definition at line 13891 of file chan_dahdi.c.

References AST_DEVICE_UNKNOWN.

13892 {
13893 #if defined(HAVE_PRI)
13894    char *device;
13895    unsigned span;
13896    int res;
13897 
13898    device = data;
13899 
13900    if (*device != 'I') {
13901       /* The request is not for an ISDN span device. */
13902       return AST_DEVICE_UNKNOWN;
13903    }
13904    res = sscanf(device, "I%30u", &span);
13905    if (res != 1 || !span || NUM_SPANS < span) {
13906       /* Bad format for ISDN span device name. */
13907       return AST_DEVICE_UNKNOWN;
13908    }
13909    device = strchr(device, '/');
13910    if (!device) {
13911       /* Bad format for ISDN span device name. */
13912       return AST_DEVICE_UNKNOWN;
13913    }
13914 
13915    /*
13916     * Since there are currently no other span devstate's defined,
13917     * it must be congestion.
13918     */
13919 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13920    ++device;
13921    if (!strcmp(device, "congestion"))
13922 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13923    {
13924       return pris[span - 1].pri.congestion_devstate;
13925    }
13926 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13927    else if (!strcmp(device, "threshold")) {
13928       return pris[span - 1].pri.threshold_devstate;
13929    }
13930    return AST_DEVICE_UNKNOWN;
13931 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13932 #else
13933    return AST_DEVICE_UNKNOWN;
13934 #endif   /* defined(HAVE_PRI) */
13935 }

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

Definition at line 4520 of file chan_dahdi.c.

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

04521 {
04522    struct dahdi_pvt *pvt;
04523    int idx;
04524    int dtmf = -1;
04525    int res;
04526 
04527    pvt = chan->tech_pvt;
04528 
04529    ast_mutex_lock(&pvt->lock);
04530 
04531    idx = dahdi_get_index(chan, pvt, 0);
04532 
04533    if ((idx != SUB_REAL) || !pvt->owner)
04534       goto out;
04535 
04536 #ifdef HAVE_PRI
04537    switch (pvt->sig) {
04538    case SIG_PRI_LIB_HANDLE_CASES:
04539       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04540       if (!res)
04541          goto out;
04542       break;
04543    default:
04544       break;
04545    }
04546 #endif
04547    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04548       goto out;
04549 
04550    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04551       struct dahdi_dialoperation zo = {
04552          .op = DAHDI_DIAL_OP_APPEND,
04553       };
04554 
04555       zo.dialstr[0] = 'T';
04556       zo.dialstr[1] = digit;
04557       zo.dialstr[2] = '\0';
04558       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04559          ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04560             chan->name, digit, strerror(errno));
04561       else
04562          pvt->dialing = 1;
04563    } else {
04564       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04565          chan->name, digit);
04566       pvt->dialing = 1;
04567       pvt->begindigit = digit;
04568    }
04569 
04570 out:
04571    ast_mutex_unlock(&pvt->lock);
04572 
04573    return 0;
04574 }

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

Definition at line 4576 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_subchannel::dfd, 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.

04577 {
04578    struct dahdi_pvt *pvt;
04579    int res = 0;
04580    int idx;
04581    int x;
04582 
04583    pvt = chan->tech_pvt;
04584 
04585    ast_mutex_lock(&pvt->lock);
04586 
04587    idx = dahdi_get_index(chan, pvt, 0);
04588 
04589    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04590       goto out;
04591 
04592 #ifdef HAVE_PRI
04593    /* This means that the digit was already sent via PRI signalling */
04594    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04595       goto out;
04596    }
04597 #endif
04598 
04599    if (pvt->begindigit) {
04600       x = -1;
04601       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04602          chan->name, digit);
04603       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04604       pvt->dialing = 0;
04605       pvt->begindigit = 0;
04606    }
04607 
04608 out:
04609    ast_mutex_unlock(&pvt->lock);
04610 
04611    return res;
04612 }

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 4988 of file chan_dahdi.c.

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

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

04989 {
04990    int res;
04991 
04992    if (p->echocanon) {
04993       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04994 
04995       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04996 
04997       if (res)
04998          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04999       else
05000          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
05001    }
05002 
05003    p->echocanon = 0;
05004 }

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

09921 {
09922    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09923       return analog_dnd(dahdichan->sig_pvt, flag);
09924    }
09925 
09926    if (flag == -1) {
09927       return dahdichan->dnd;
09928    }
09929 
09930    /* Do not disturb */
09931    dahdichan->dnd = flag;
09932    ast_verb(3, "%s DND on channel %d\n",
09933          flag? "Enabled" : "Disabled",
09934          dahdichan->channel);
09935    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09936          "Channel: DAHDI/%d\r\n"
09937          "Status: %s\r\n", dahdichan->channel,
09938          flag? "enabled" : "disabled");
09939 
09940    return 0;
09941 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 4916 of file chan_dahdi.c.

References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::head, LOG_WARNING, dahdi_pvt::sig, SIG_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_setoption(), handle_init_event(), and my_set_echocanceller().

04917 {
04918    int res;
04919    if (!p)
04920       return;
04921    if (p->echocanon) {
04922       ast_debug(1, "Echo cancellation already on\n");
04923       return;
04924    }
04925    if (p->digital) {
04926       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04927       return;
04928    }
04929    if (p->echocancel.head.tap_length) {
04930 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04931       switch (p->sig) {
04932 #if defined(HAVE_PRI)
04933       case SIG_PRI_LIB_HANDLE_CASES:
04934          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04935             /*
04936              * PRI nobch pseudo channel.  Does not need ec anyway.
04937              * Does not handle ioctl(DAHDI_AUDIOMODE)
04938              */
04939             return;
04940          }
04941          /* Fall through */
04942 #endif   /* defined(HAVE_PRI) */
04943 #if defined(HAVE_SS7)
04944       case SIG_SS7:
04945 #endif   /* defined(HAVE_SS7) */
04946          {
04947             int x = 1;
04948 
04949             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04950             if (res)
04951                ast_log(LOG_WARNING,
04952                   "Unable to enable audio mode on channel %d (%s)\n",
04953                   p->channel, strerror(errno));
04954          }
04955          break;
04956       default:
04957          break;
04958       }
04959 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04960       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04961       if (res) {
04962          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04963       } else {
04964          p->echocanon = 1;
04965          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04966       }
04967    } else
04968       ast_debug(1, "No echo cancellation requested\n");
04969 }

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

Definition at line 8941 of file chan_dahdi.c.

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

08942 {
08943    struct dahdi_pvt *p = ast->tech_pvt;
08944    struct ast_frame *f;
08945    ast_mutex_lock(&p->lock);
08946    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08947       struct analog_pvt *analog_p = p->sig_pvt;
08948       f = analog_exception(analog_p, ast);
08949    } else {
08950       f = __dahdi_exception(ast);
08951    }
08952    ast_mutex_unlock(&p->lock);
08953    return f;
08954 }

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

Definition at line 16058 of file chan_dahdi.c.

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

Referenced by action_transfer(), and action_transferhangup().

16059 {
16060    if (p) {
16061       switch (mode) {
16062       case TRANSFER:
16063          p->fake_event = DAHDI_EVENT_WINKFLASH;
16064          break;
16065       case HANGUP:
16066          p->fake_event = DAHDI_EVENT_ONHOOK;
16067          break;
16068       default:
16069          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
16070       }
16071    }
16072    return 0;
16073 }

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

Definition at line 7613 of file chan_dahdi.c.

References ast_channel::_state, analog_fixup(), analog_lib_handles(), AST_CONTROL_RINGING, ast_debug, ast_mutex_lock, ast_mutex_unlock, AST_STATE_RINGING, dahdi_pvt::channel, dahdi_indicate(), dahdi_sig_pri_lib_handles(), dahdi_unlink(), dahdi_pvt::lock, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, sig_pri_fixup(), dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_fixup(), dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().

07614 {
07615    struct dahdi_pvt *p = newchan->tech_pvt;
07616    int x;
07617 
07618    ast_mutex_lock(&p->lock);
07619 
07620    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07621    if (p->owner == oldchan) {
07622       p->owner = newchan;
07623    }
07624    for (x = 0; x < 3; x++) {
07625       if (p->subs[x].owner == oldchan) {
07626          if (!x) {
07627             dahdi_unlink(NULL, p, 0);
07628          }
07629          p->subs[x].owner = newchan;
07630       }
07631    }
07632    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07633       analog_fixup(oldchan, newchan, p->sig_pvt);
07634 #if defined(HAVE_PRI)
07635    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07636       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07637 #endif   /* defined(HAVE_PRI) */
07638 #if defined(HAVE_SS7)
07639    } else if (p->sig == SIG_SS7) {
07640       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07641 #endif   /* defined(HAVE_SS7) */
07642    }
07643    update_conf(p);
07644 
07645    ast_mutex_unlock(&p->lock);
07646 
07647    if (newchan->_state == AST_STATE_RINGING) {
07648       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07649    }
07650    return 0;
07651 }

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

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

06969 {
06970    struct dahdi_pvt *p = chan->tech_pvt;
06971    int res = 0;
06972 
06973    if (!p) {
06974       /* No private structure! */
06975       *buf = '\0';
06976       return -1;
06977    }
06978 
06979    if (!strcasecmp(data, "rxgain")) {
06980       ast_mutex_lock(&p->lock);
06981       snprintf(buf, len, "%f", p->rxgain);
06982       ast_mutex_unlock(&p->lock);
06983    } else if (!strcasecmp(data, "txgain")) {
06984       ast_mutex_lock(&p->lock);
06985       snprintf(buf, len, "%f", p->txgain);
06986       ast_mutex_unlock(&p->lock);
06987    } else if (!strcasecmp(data, "dahdi_channel")) {
06988       ast_mutex_lock(&p->lock);
06989       snprintf(buf, len, "%d", p->channel);
06990       ast_mutex_unlock(&p->lock);
06991    } else if (!strcasecmp(data, "dahdi_span")) {
06992       ast_mutex_lock(&p->lock);
06993       snprintf(buf, len, "%d", p->span);
06994       ast_mutex_unlock(&p->lock);
06995    } else if (!strcasecmp(data, "dahdi_type")) {
06996       ast_mutex_lock(&p->lock);
06997       switch (p->sig) {
06998 #if defined(HAVE_OPENR2)
06999       case SIG_MFCR2:
07000          ast_copy_string(buf, "mfc/r2", len);
07001          break;
07002 #endif   /* defined(HAVE_OPENR2) */
07003 #if defined(HAVE_PRI)
07004       case SIG_PRI_LIB_HANDLE_CASES:
07005          ast_copy_string(buf, "pri", len);
07006          break;
07007 #endif   /* defined(HAVE_PRI) */
07008       case 0:
07009          ast_copy_string(buf, "pseudo", len);
07010          break;
07011 #if defined(HAVE_SS7)
07012       case SIG_SS7:
07013          ast_copy_string(buf, "ss7", len);
07014          break;
07015 #endif   /* defined(HAVE_SS7) */
07016       default:
07017          /* The only thing left is analog ports. */
07018          ast_copy_string(buf, "analog", len);
07019          break;
07020       }
07021       ast_mutex_unlock(&p->lock);
07022 #if defined(HAVE_PRI)
07023 #if defined(HAVE_PRI_REVERSE_CHARGE)
07024    } else if (!strcasecmp(data, "reversecharge")) {
07025       ast_mutex_lock(&p->lock);
07026       switch (p->sig) {
07027       case SIG_PRI_LIB_HANDLE_CASES:
07028          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07029          break;
07030       default:
07031          *buf = '\0';
07032          res = -1;
07033          break;
07034       }
07035       ast_mutex_unlock(&p->lock);
07036 #endif
07037 #if defined(HAVE_PRI_SETUP_KEYPAD)
07038    } else if (!strcasecmp(data, "keypad_digits")) {
07039       ast_mutex_lock(&p->lock);
07040       switch (p->sig) {
07041       case SIG_PRI_LIB_HANDLE_CASES:
07042          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07043             len);
07044          break;
07045       default:
07046          *buf = '\0';
07047          res = -1;
07048          break;
07049       }
07050       ast_mutex_unlock(&p->lock);
07051 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
07052    } else if (!strcasecmp(data, "no_media_path")) {
07053       ast_mutex_lock(&p->lock);
07054       switch (p->sig) {
07055       case SIG_PRI_LIB_HANDLE_CASES:
07056          /*
07057           * TRUE if the call is on hold or is call waiting because
07058           * there is no media path available.
07059           */
07060          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07061          break;
07062       default:
07063          *buf = '\0';
07064          res = -1;
07065          break;
07066       }
07067       ast_mutex_unlock(&p->lock);
07068 #endif   /* defined(HAVE_PRI) */
07069    } else {
07070       *buf = '\0';
07071       res = -1;
07072    }
07073 
07074    return res;
07075 }

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

Definition at line 7107 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_subchannel::dfd, dahdi_pvt::echocanon, errno, dahdi_pvt::lock, LOG_WARNING, parse_buffers_policy(), SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

07108 {
07109    struct dahdi_pvt *p = chan->tech_pvt;
07110    int res = 0;
07111 
07112    if (!p) {
07113       /* No private structure! */
07114       return -1;
07115    }
07116 
07117    if (!strcasecmp(data, "buffers")) {
07118       int num_bufs, policy;
07119 
07120       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07121          struct dahdi_bufferinfo bi = {
07122             .txbufpolicy = policy,
07123             .rxbufpolicy = policy,
07124             .bufsize = p->bufsize,
07125             .numbufs = num_bufs,
07126          };
07127          int bpres;
07128 
07129          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07130             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07131          } else {
07132             p->bufferoverrideinuse = 1;
07133          }
07134       } else {
07135          res = -1;
07136       }
07137    } else if (!strcasecmp(data, "echocan_mode")) {
07138       if (!strcasecmp(value, "on")) {
07139          ast_mutex_lock(&p->lock);
07140          dahdi_enable_ec(p);
07141          ast_mutex_unlock(&p->lock);
07142       } else if (!strcasecmp(value, "off")) {
07143          ast_mutex_lock(&p->lock);
07144          dahdi_disable_ec(p);
07145          ast_mutex_unlock(&p->lock);
07146 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07147       } else if (!strcasecmp(value, "fax")) {
07148          int blah = 1;
07149 
07150          ast_mutex_lock(&p->lock);
07151          if (!p->echocanon) {
07152             dahdi_enable_ec(p);
07153          }
07154          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07155             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07156          }
07157          ast_mutex_unlock(&p->lock);
07158       } else if (!strcasecmp(value, "voice")) {
07159          int blah = 0;
07160 
07161          ast_mutex_lock(&p->lock);
07162          if (!p->echocanon) {
07163             dahdi_enable_ec(p);
07164          }
07165          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07166             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07167          }
07168          ast_mutex_unlock(&p->lock);
07169 #endif
07170       } else {
07171          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07172          res = -1;
07173       }
07174    } else {
07175       res = -1;
07176    }
07177 
07178    return res;
07179 }

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 495 of file chan_dahdi.c.

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

00496 {
00497    int j;
00498    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00499       return -1;
00500    return j;
00501 }

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

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

07791 {
07792    struct dahdi_pvt *p = ast->tech_pvt;
07793    struct ast_frame *f = *dest;
07794 
07795    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07796       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07797       (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
07798 
07799    if (p->confirmanswer) {
07800       if (f->frametype == AST_FRAME_DTMF_END) {
07801          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07802          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07803             of a DTMF digit */
07804          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07805          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07806          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07807          p->confirmanswer = 0;
07808       } else {
07809          p->subs[idx].f.frametype = AST_FRAME_NULL;
07810          p->subs[idx].f.subclass.integer = 0;
07811       }
07812       *dest = &p->subs[idx].f;
07813    } else if (p->callwaitcas) {
07814       if (f->frametype == AST_FRAME_DTMF_END) {
07815          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07816             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07817             ast_free(p->cidspill);
07818             p->cidspill = NULL;
07819             send_cwcidspill(p);
07820          }
07821          p->callwaitcas = 0;
07822       }
07823       p->subs[idx].f.frametype = AST_FRAME_NULL;
07824       p->subs[idx].f.subclass.integer = 0;
07825       *dest = &p->subs[idx].f;
07826    } else if (f->subclass.integer == 'f') {
07827       if (f->frametype == AST_FRAME_DTMF_END) {
07828          /* Fax tone -- Handle and return NULL */
07829          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07830             /* If faxbuffers are configured, use them for the fax transmission */
07831             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07832                struct dahdi_bufferinfo bi = {
07833                   .txbufpolicy = p->faxbuf_policy,
07834                   .bufsize = p->bufsize,
07835                   .numbufs = p->faxbuf_no
07836                };
07837                int res;
07838 
07839                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07840                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07841                } else {
07842                   p->bufferoverrideinuse = 1;
07843                }
07844             }
07845             p->faxhandled = 1;
07846             if (p->dsp) {
07847                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07848                ast_dsp_set_features(p->dsp, p->dsp_features);
07849                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07850             }
07851             if (strcmp(ast->exten, "fax")) {
07852                const char *target_context = S_OR(ast->macrocontext, ast->context);
07853 
07854                /* We need to unlock 'ast' here because ast_exists_extension has the
07855                 * potential to start autoservice on the channel. Such action is prone
07856                 * to deadlock.
07857                 */
07858                ast_mutex_unlock(&p->lock);
07859                ast_channel_unlock(ast);
07860                if (ast_exists_extension(ast, target_context, "fax", 1,
07861                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07862                   ast_channel_lock(ast);
07863                   ast_mutex_lock(&p->lock);
07864                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07865                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07866                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07867                   if (ast_async_goto(ast, target_context, "fax", 1))
07868                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07869                } else {
07870                   ast_channel_lock(ast);
07871                   ast_mutex_lock(&p->lock);
07872                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07873                }
07874             } else {
07875                ast_debug(1, "Already in a fax extension, not redirecting\n");
07876             }
07877          } else {
07878             ast_debug(1, "Fax already handled\n");
07879          }
07880          dahdi_confmute(p, 0);
07881       }
07882       p->subs[idx].f.frametype = AST_FRAME_NULL;
07883       p->subs[idx].f.subclass.integer = 0;
07884       *dest = &p->subs[idx].f;
07885    }
07886 }

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

Definition at line 7916 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_lock, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_null_frame, 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, dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, CANPROGRESSDETECT, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, check_for_conference(), dahdi_pvt::cid_name, cid_name, dahdi_pvt::cid_num, cid_num, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, 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::dialednone, dahdi_pvt::dialing, DLA_LOCK, DLA_UNLOCK, dahdi_pvt::dop, dahdi_pvt::dsp, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), dahdi_subchannel::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, LOG_WARNING, ast_frame::mallocd, MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, ast_party_id::name, dahdi_subchannel::needanswer, 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, dahdi_pvt::owner, dahdi_subchannel::owner, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, ast_frame::ptr, dahdi_pvt::pulsedial, 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_dial_complete(), 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().

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

static int dahdi_hangup ( struct ast_channel ast  )  [static]

Definition at line 6191 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_confmute(), dahdi_disable_ec(), dahdi_get_index, 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, 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::mohsuggest, dahdi_pvt::muting, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, 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::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.

06192 {
06193    int res = 0;
06194    int idx,x;
06195    int law;
06196    /*static int restore_gains(struct dahdi_pvt *p);*/
06197    struct dahdi_pvt *p = ast->tech_pvt;
06198    struct dahdi_params par;
06199 
06200    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06201    if (!ast->tech_pvt) {
06202       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06203       return 0;
06204    }
06205 
06206    ast_mutex_lock(&p->lock);
06207    p->exten[0] = '\0';
06208    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06209       dahdi_confmute(p, 0);
06210       restore_gains(p);
06211       p->ignoredtmf = 0;
06212       p->waitingfordt.tv_sec = 0;
06213 
06214       res = analog_hangup(p->sig_pvt, ast);
06215       revert_fax_buffers(p, ast);
06216 
06217       goto hangup_out;
06218    } else {
06219       p->cid_num[0] = '\0';
06220       p->cid_name[0] = '\0';
06221       p->cid_subaddr[0] = '\0';
06222    }
06223 
06224 #if defined(HAVE_PRI)
06225    if (dahdi_sig_pri_lib_handles(p->sig)) {
06226       x = 1;
06227       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06228 
06229       dahdi_confmute(p, 0);
06230       p->muting = 0;
06231       restore_gains(p);
06232       if (p->dsp) {
06233          ast_dsp_free(p->dsp);
06234          p->dsp = NULL;
06235       }
06236       p->ignoredtmf = 0;
06237 
06238       /* Real channel, do some fixup */
06239       p->subs[SUB_REAL].owner = NULL;
06240       p->subs[SUB_REAL].needbusy = 0;
06241       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06242 
06243       p->owner = NULL;
06244       p->cid_tag[0] = '\0';
06245       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06246       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06247       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06248       p->outgoing = 0;
06249       p->digital = 0;
06250       p->faxhandled = 0;
06251       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06252 
06253       revert_fax_buffers(p, ast);
06254 
06255       p->law = p->law_default;
06256       law = p->law_default;
06257       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06258       if (res < 0) {
06259          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06260             p->channel, strerror(errno));
06261       }
06262 
06263       sig_pri_hangup(p->sig_pvt, ast);
06264 
06265       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06266       dahdi_disable_ec(p);
06267 
06268       x = 0;
06269       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06270       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06271 
06272       p->rdnis[0] = '\0';
06273       update_conf(p);
06274       reset_conf(p);
06275 
06276       /* Restore data mode */
06277       x = 0;
06278       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06279 
06280       if (num_restart_pending == 0) {
06281          restart_monitor();
06282       }
06283       goto hangup_out;
06284    }
06285 #endif   /* defined(HAVE_PRI) */
06286 
06287 #if defined(HAVE_SS7)
06288    if (p->sig == SIG_SS7) {
06289       x = 1;
06290       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06291 
06292       dahdi_confmute(p, 0);
06293       p->muting = 0;
06294       restore_gains(p);
06295       if (p->dsp) {
06296          ast_dsp_free(p->dsp);
06297          p->dsp = NULL;
06298       }
06299       p->ignoredtmf = 0;
06300 
06301       /* Real channel, do some fixup */
06302       p->subs[SUB_REAL].owner = NULL;
06303       p->subs[SUB_REAL].needbusy = 0;
06304       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06305 
06306       p->owner = NULL;
06307       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06308       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06309       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06310       p->outgoing = 0;
06311       p->digital = 0;
06312       p->faxhandled = 0;
06313       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06314 
06315       revert_fax_buffers(p, ast);
06316 
06317       p->law = p->law_default;
06318       law = p->law_default;
06319       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06320       if (res < 0) {
06321          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06322             p->channel, strerror(errno));
06323       }
06324 
06325       sig_ss7_hangup(p->sig_pvt, ast);
06326 
06327       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06328       dahdi_disable_ec(p);
06329 
06330       x = 0;
06331       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06332       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06333 
06334       update_conf(p);
06335       reset_conf(p);
06336 
06337       /* Restore data mode */
06338       x = 0;
06339       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06340 
06341       if (num_restart_pending == 0) {
06342          restart_monitor();
06343       }
06344       goto hangup_out;
06345    }
06346 #endif   /* defined(HAVE_SS7) */
06347 
06348    idx = dahdi_get_index(ast, p, 1);
06349 
06350    dahdi_confmute(p, 0);
06351    p->muting = 0;
06352    restore_gains(p);
06353    if (p->origcid_num) {
06354       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06355       ast_free(p->origcid_num);
06356       p->origcid_num = NULL;
06357    }
06358    if (p->origcid_name) {
06359       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06360       ast_free(p->origcid_name);
06361       p->origcid_name = NULL;
06362    }
06363    if (p->dsp)
06364       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06365 
06366    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06367       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06368    p->ignoredtmf = 0;
06369 
06370    if (idx > -1) {
06371       /* Real channel, do some fixup */
06372       p->subs[idx].owner = NULL;
06373       p->subs[idx].needanswer = 0;
06374       p->subs[idx].needflash = 0;
06375       p->subs[idx].needringing = 0;
06376       p->subs[idx].needbusy = 0;
06377       p->subs[idx].needcongestion = 0;
06378       p->subs[idx].linear = 0;
06379       p->polarity = POLARITY_IDLE;
06380       dahdi_setlinear(p->subs[idx].dfd, 0);
06381       if (idx == SUB_REAL) {
06382          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06383             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06384             if (p->subs[SUB_CALLWAIT].inthreeway) {
06385                /* We had flipped over to answer a callwait and now it's gone */
06386                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06387                /* Move to the call-wait, but un-own us until they flip back. */
06388                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06389                unalloc_sub(p, SUB_CALLWAIT);
06390                p->owner = NULL;
06391             } else {
06392                /* The three way hung up, but we still have a call wait */
06393                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06394                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06395                unalloc_sub(p, SUB_THREEWAY);
06396                if (p->subs[SUB_REAL].inthreeway) {
06397                   /* This was part of a three way call.  Immediately make way for
06398                      another call */
06399                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06400                   p->owner = p->subs[SUB_REAL].owner;
06401                } else {
06402                   /* This call hasn't been completed yet...  Set owner to NULL */
06403                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06404                   p->owner = NULL;
06405                }
06406                p->subs[SUB_REAL].inthreeway = 0;
06407             }
06408          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06409             /* Move to the call-wait and switch back to them. */
06410             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06411             unalloc_sub(p, SUB_CALLWAIT);
06412             p->owner = p->subs[SUB_REAL].owner;
06413             if (p->owner->_state != AST_STATE_UP)
06414                p->subs[SUB_REAL].needanswer = 1;
06415             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06416                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06417          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06418             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06419             unalloc_sub(p, SUB_THREEWAY);
06420             if (p->subs[SUB_REAL].inthreeway) {
06421                /* This was part of a three way call.  Immediately make way for
06422                   another call */
06423                ast_debug(1, "Call was complete, setting owner to former third call\n");
06424                p->owner = p->subs[SUB_REAL].owner;
06425             } else {
06426                /* This call hasn't been completed yet...  Set owner to NULL */
06427                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06428                p->owner = NULL;
06429             }
06430             p->subs[SUB_REAL].inthreeway = 0;
06431          }
06432       } else if (idx == SUB_CALLWAIT) {
06433          /* Ditch the holding callwait call, and immediately make it availabe */
06434          if (p->subs[SUB_CALLWAIT].inthreeway) {
06435             /* This is actually part of a three way, placed on hold.  Place the third part
06436                on music on hold now */
06437             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06438                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06439                   S_OR(p->mohsuggest, NULL),
06440                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06441             }
06442             p->subs[SUB_THREEWAY].inthreeway = 0;
06443             /* Make it the call wait now */
06444             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06445             unalloc_sub(p, SUB_THREEWAY);
06446          } else
06447             unalloc_sub(p, SUB_CALLWAIT);
06448       } else if (idx == SUB_THREEWAY) {
06449          if (p->subs[SUB_CALLWAIT].inthreeway) {
06450             /* The other party of the three way call is currently in a call-wait state.
06451                Start music on hold for them, and take the main guy out of the third call */
06452             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06453                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06454                   S_OR(p->mohsuggest, NULL),
06455                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06456             }
06457             p->subs[SUB_CALLWAIT].inthreeway = 0;
06458          }
06459          p->subs[SUB_REAL].inthreeway = 0;
06460          /* If this was part of a three way call index, let us make
06461             another three way call */
06462          unalloc_sub(p, SUB_THREEWAY);
06463       } else {
06464          /* This wasn't any sort of call, but how are we an index? */
06465          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06466       }
06467    }
06468 
06469    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06470       p->owner = NULL;
06471       p->ringt = 0;
06472       p->distinctivering = 0;
06473       p->confirmanswer = 0;
06474       p->outgoing = 0;
06475       p->digital = 0;
06476       p->faxhandled = 0;
06477       p->pulsedial = 0;
06478       if (p->dsp) {
06479          ast_dsp_free(p->dsp);
06480          p->dsp = NULL;
06481       }
06482 
06483       revert_fax_buffers(p, ast);
06484 
06485       p->law = p->law_default;
06486       law = p->law_default;
06487       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06488       if (res < 0)
06489          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06490       /* Perform low level hangup if no owner left */
06491 #ifdef HAVE_OPENR2
06492       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06493          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06494          /* If it's an incoming call, check the mfcr2_forced_release setting */
06495          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06496             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06497          } else {
06498             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06499             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06500             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06501                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06502             dahdi_r2_disconnect_call(p, r2cause);
06503          }
06504       } else if (p->mfcr2call) {
06505          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06506          /* since ast_request() was called but not ast_call() we have not yet dialed
06507          and the openr2 stack will not call on_call_end callback, we need to unset
06508          the mfcr2call flag and bump the monitor count so the monitor thread can take
06509          care of this channel events from now on */
06510          p->mfcr2call = 0;
06511       }
06512 #endif
06513       switch (p->sig) {
06514       case SIG_SS7:
06515       case SIG_MFCR2:
06516       case SIG_PRI_LIB_HANDLE_CASES:
06517       case 0:
06518          break;
06519       default:
06520          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06521          break;
06522       }
06523       if (res < 0) {
06524          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06525       }
06526       switch (p->sig) {
06527       case SIG_FXOGS:
06528       case SIG_FXOLS:
06529       case SIG_FXOKS:
06530          memset(&par, 0, sizeof(par));
06531          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06532          if (!res) {
06533             struct analog_pvt *analog_p = p->sig_pvt;
06534 #if 0
06535             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06536 #endif
06537             /* If they're off hook, try playing congestion */
06538             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06539                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06540             else
06541                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06542             analog_p->fxsoffhookstate = par.rxisoffhook;
06543          }
06544          break;
06545       case SIG_FXSGS:
06546       case SIG_FXSLS:
06547       case SIG_FXSKS:
06548          /* Make sure we're not made available for at least two seconds assuming
06549          we were actually used for an inbound or outbound call. */
06550          if (ast->_state != AST_STATE_RESERVED) {
06551             time(&p->guardtime);
06552             p->guardtime += 2;
06553          }
06554          break;
06555       default:
06556          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06557          break;
06558       }
06559       if (p->sig)
06560          dahdi_disable_ec(p);
06561       x = 0;
06562       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06563       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06564       p->didtdd = 0;
06565       p->callwaitcas = 0;
06566       p->callwaiting = p->permcallwaiting;
06567       p->hidecallerid = p->permhidecallerid;
06568       p->waitingfordt.tv_sec = 0;
06569       p->dialing = 0;
06570       p->rdnis[0] = '\0';
06571       update_conf(p);
06572       reset_conf(p);
06573       /* Restore data mode */
06574       switch (p->sig) {
06575       case SIG_PRI_LIB_HANDLE_CASES:
06576       case SIG_SS7:
06577          x = 0;
06578          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06579          break;
06580       default:
06581          break;
06582       }
06583       if (num_restart_pending == 0)
06584          restart_monitor();
06585    }
06586 
06587    p->callwaitingrepeat = 0;
06588    p->cidcwexpire = 0;
06589    p->cid_suppress_expire = 0;
06590    p->oprmode = 0;
06591 hangup_out:
06592    ast->tech_pvt = NULL;
06593    ast_free(p->cidspill);
06594    p->cidspill = NULL;
06595 
06596    ast_mutex_unlock(&p->lock);
06597    ast_verb(3, "Hungup '%s'\n", ast->name);
06598 
06599    ast_mutex_lock(&iflock);
06600    if (p->restartpending) {
06601       num_restart_pending--;
06602    }
06603 
06604    if (p->destroy) {
06605       destroy_channel(p, 0);
06606    }
06607    ast_mutex_unlock(&iflock);
06608 
06609    ast_module_unref(ast_module_info->self);
06610    return 0;
06611 }

static void dahdi_iflist_extract ( struct dahdi_pvt pvt  )  [static]

Definition at line 5584 of file chan_dahdi.c.

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

Referenced by destroy_dahdi_pvt().

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

static void dahdi_iflist_insert ( struct dahdi_pvt pvt  )  [static]

Definition at line 5534 of file chan_dahdi.c.

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

Referenced by duplicate_pseudo(), and mkintf().

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

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

Definition at line 9479 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, LOG_WARNING, dahdi_pvt::mohinterpret, 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.

Referenced by dahdi_fixup().

09480 {
09481    struct dahdi_pvt *p = chan->tech_pvt;
09482    int res=-1;
09483    int idx;
09484    int func = DAHDI_FLASH;
09485 
09486    ast_mutex_lock(&p->lock);
09487    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09488    switch (p->sig) {
09489 #if defined(HAVE_PRI)
09490    case SIG_PRI_LIB_HANDLE_CASES:
09491       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09492       ast_mutex_unlock(&p->lock);
09493       return res;
09494 #endif   /* defined(HAVE_PRI) */
09495 #if defined(HAVE_SS7)
09496    case SIG_SS7:
09497       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09498       ast_mutex_unlock(&p->lock);
09499       return res;
09500 #endif   /* defined(HAVE_SS7) */
09501    default:
09502       break;
09503    }
09504 #ifdef HAVE_OPENR2
09505    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09506       ast_mutex_unlock(&p->lock);
09507       /* if this is an R2 call and the call is not yet accepted, we don't want the
09508          tone indications to mess up with the MF tones */
09509       return 0;
09510    }
09511 #endif
09512    idx = dahdi_get_index(chan, p, 0);
09513    if (idx == SUB_REAL) {
09514       switch (condition) {
09515       case AST_CONTROL_BUSY:
09516          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09517          break;
09518       case AST_CONTROL_RINGING:
09519          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09520 
09521          if (chan->_state != AST_STATE_UP) {
09522             if ((chan->_state != AST_STATE_RING) ||
09523                ((p->sig != SIG_FXSKS) &&
09524              (p->sig != SIG_FXSLS) &&
09525              (p->sig != SIG_FXSGS)))
09526             ast_setstate(chan, AST_STATE_RINGING);
09527          }
09528          break;
09529       case AST_CONTROL_INCOMPLETE:
09530          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09531          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09532          res = 0;
09533          break;
09534       case AST_CONTROL_PROCEEDING:
09535          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09536          /* don't continue in ast_indicate */
09537          res = 0;
09538          break;
09539       case AST_CONTROL_PROGRESS:
09540          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09541          /* don't continue in ast_indicate */
09542          res = 0;
09543          break;
09544       case AST_CONTROL_CONGESTION:
09545          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09546          switch (chan->hangupcause) {
09547          case AST_CAUSE_USER_BUSY:
09548          case AST_CAUSE_NORMAL_CLEARING:
09549          case 0:/* Cause has not been set. */
09550             /* Supply a more appropriate cause. */
09551             chan->hangupcause = AST_CAUSE_CONGESTION;
09552             break;
09553          default:
09554             break;
09555          }
09556          break;
09557       case AST_CONTROL_HOLD:
09558          ast_moh_start(chan, data, p->mohinterpret);
09559          break;
09560       case AST_CONTROL_UNHOLD:
09561          ast_moh_stop(chan);
09562          break;
09563       case AST_CONTROL_RADIO_KEY:
09564          if (p->radio)
09565             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09566          res = 0;
09567          break;
09568       case AST_CONTROL_RADIO_UNKEY:
09569          if (p->radio)
09570             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09571          res = 0;
09572          break;
09573       case AST_CONTROL_FLASH:
09574          /* flash hookswitch */
09575          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09576             /* Clear out the dial buffer */
09577             p->dop.dialstr[0] = '\0';
09578             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09579                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09580                   chan->name, strerror(errno));
09581             } else
09582                res = 0;
09583          } else
09584             res = 0;
09585          break;
09586       case AST_CONTROL_SRCUPDATE:
09587          res = 0;
09588          break;
09589       case -1:
09590          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09591          break;
09592       }
09593    } else {
09594       res = 0;
09595    }
09596    ast_mutex_unlock(&p->lock);
09597    return res;
09598 }

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

Definition at line 7237 of file chan_dahdi.c.

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

Referenced by dahdi_bridge().

07237                                                                           {
07238    int x;
07239    if (!slave || !master) {
07240       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07241       return;
07242    }
07243    for (x = 0; x < MAX_SLAVES; x++) {
07244       if (!master->slaves[x]) {
07245          master->slaves[x] = slave;
07246          break;
07247       }
07248    }
07249    if (x >= MAX_SLAVES) {
07250       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07251       master->slaves[MAX_SLAVES - 1] = slave;
07252    }
07253    if (slave->master)
07254       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07255    slave->master = master;
07256 
07257    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07258 }

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

Definition at line 3832 of file chan_dahdi.c.

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

Referenced by wakeup_sub().

03833 {
03834    for (;;) {
03835       if (!pvt->subs[sub_idx].owner) {
03836          /* No subchannel owner pointer */
03837          break;
03838       }
03839       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03840          /* Got subchannel owner lock */
03841          break;
03842       }
03843       /* We must unlock the private to avoid the possibility of a deadlock */
03844       DEADLOCK_AVOIDANCE(&pvt->lock);
03845    }
03846 }

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

Definition at line 9648 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_DEVSTATE_NOT_CACHABLE, 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_FLAG_DISABLE_DEVSTATE_CACHE, 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, dahdi_pvt::cc_params, CHAN_PSEUDO, dahdi_pvt::channel, 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_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_channel::flags, 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, LOG_WARNING, dahdi_pvt::muting, ast_variable::name, ast_party_id::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::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, 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_request(), do_monitor(), handle_init_event(), mwi_thread(), and my_new_analog_ast_channel().

09649 {
09650    struct ast_channel *tmp;
09651    format_t deflaw;
09652    int x;
09653    int features;
09654    struct ast_str *chan_name;
09655    struct ast_variable *v;
09656    char *dashptr;
09657    char device_name[AST_CHANNEL_NAME];
09658 
09659    if (i->subs[idx].owner) {
09660       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09661       return NULL;
09662    }
09663 
09664 #if defined(HAVE_PRI)
09665    /*
09666     * The dnid has been stuffed with the called-number[:subaddress]
09667     * by dahdi_request() for outgoing calls.
09668     */
09669    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09670 #else
09671    chan_name = create_channel_name(i);
09672 #endif   /* defined(HAVE_PRI) */
09673    if (!chan_name) {
09674       return NULL;
09675    }
09676 
09677    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));
09678    ast_free(chan_name);
09679    if (!tmp)
09680       return NULL;
09681    tmp->tech = &dahdi_tech;
09682 #if defined(HAVE_PRI)
09683    if (i->pri) {
09684       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09685    }
09686 #endif   /* defined(HAVE_PRI) */
09687    ast_channel_cc_params_init(tmp, i->cc_params);
09688    if (law) {
09689       i->law = law;
09690       if (law == DAHDI_LAW_ALAW) {
09691          deflaw = AST_FORMAT_ALAW;
09692       } else {
09693          deflaw = AST_FORMAT_ULAW;
09694       }
09695    } else {
09696       switch (i->sig) {
09697       case SIG_PRI_LIB_HANDLE_CASES:
09698          /* Make sure companding law is known. */
09699          i->law = (i->law_default == DAHDI_LAW_ALAW)
09700             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09701          break;
09702       default:
09703          i->law = i->law_default;
09704          break;
09705       }
09706       if (i->law_default == DAHDI_LAW_ALAW) {
09707          deflaw = AST_FORMAT_ALAW;
09708       } else {
09709          deflaw = AST_FORMAT_ULAW;
09710       }
09711    }
09712    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09713    tmp->nativeformats = deflaw;
09714    /* Start out assuming ulaw since it's smaller :) */
09715    tmp->rawreadformat = deflaw;
09716    tmp->readformat = deflaw;
09717    tmp->rawwriteformat = deflaw;
09718    tmp->writeformat = deflaw;
09719    i->subs[idx].linear = 0;
09720    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09721    features = 0;
09722    if (idx == SUB_REAL) {
09723       if (i->busydetect && CANBUSYDETECT(i))
09724          features |= DSP_FEATURE_BUSY_DETECT;
09725       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09726          features |= DSP_FEATURE_CALL_PROGRESS;
09727       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09728          features |= DSP_FEATURE_WAITDIALTONE;
09729       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09730          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09731          features |= DSP_FEATURE_FAX_DETECT;
09732       }
09733       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09734       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09735          i->hardwaredtmf = 0;
09736          features |= DSP_FEATURE_DIGIT_DETECT;
09737       } else if (NEED_MFDETECT(i)) {
09738          i->hardwaredtmf = 1;
09739          features |= DSP_FEATURE_DIGIT_DETECT;
09740       }
09741    }
09742    if (features) {
09743       if (i->dsp) {
09744          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09745       } else {
09746          if (i->channel != CHAN_PSEUDO)
09747             i->dsp = ast_dsp_new();
09748          else
09749             i->dsp = NULL;
09750          if (i->dsp) {
09751             i->dsp_features = features;
09752 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09753             /* We cannot do progress detection until receive PROGRESS message */
09754             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09755                /* Remember requested DSP features, don't treat
09756                   talking as ANSWER */
09757                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09758                features = 0;
09759             }
09760 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09761             ast_dsp_set_features(i->dsp, features);
09762             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09763             if (!ast_strlen_zero(progzone))
09764                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09765             if (i->busydetect && CANBUSYDETECT(i)) {
09766                if(i->silencethreshold > 0)
09767                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
09768                ast_dsp_set_busy_count(i->dsp, i->busycount);
09769                if(i->busytonelength > 0)
09770                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
09771                if((i->busytonelength == i->busyquietlength) && i->busycompare)
09772                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
09773             }
09774          }
09775       }
09776    }
09777 
09778    if (state == AST_STATE_RING)
09779       tmp->rings = 1;
09780    tmp->tech_pvt = i;
09781    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09782       /* Only FXO signalled stuff can be picked up */
09783       tmp->callgroup = i->callgroup;
09784       tmp->pickupgroup = i->pickupgroup;
09785    }
09786    if (!ast_strlen_zero(i->parkinglot))
09787       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09788    if (!ast_strlen_zero(i->language))
09789       ast_string_field_set(tmp, language, i->language);
09790    if (!i->owner)
09791       i->owner = tmp;
09792    if (!ast_strlen_zero(i->accountcode))
09793       ast_string_field_set(tmp, accountcode, i->accountcode);
09794    if (i->amaflags)
09795       tmp->amaflags = i->amaflags;
09796    i->subs[idx].owner = tmp;
09797    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09798    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09799       ast_string_field_set(tmp, call_forward, i->call_forward);
09800    }
09801    /* If we've been told "no ADSI" then enforce it */
09802    if (!i->adsi)
09803       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09804    if (!ast_strlen_zero(i->exten))
09805       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09806    if (!ast_strlen_zero(i->rdnis)) {
09807       tmp->redirecting.from.number.valid = 1;
09808       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09809    }
09810    if (!ast_strlen_zero(i->dnid)) {
09811       tmp->dialed.number.str = ast_strdup(i->dnid);
09812    }
09813 
09814    /* Don't use ast_set_callerid() here because it will
09815     * generate a needless NewCallerID event */
09816 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09817    if (!ast_strlen_zero(i->cid_ani)) {
09818       tmp->caller.ani.number.valid = 1;
09819       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09820    } else if (!ast_strlen_zero(i->cid_num)) {
09821       tmp->caller.ani.number.valid = 1;
09822       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09823    }
09824 #else
09825    if (!ast_strlen_zero(i->cid_num)) {
09826       tmp->caller.ani.number.valid = 1;
09827       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09828    }
09829 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09830    tmp->caller.id.name.presentation = i->callingpres;
09831    tmp->caller.id.number.presentation = i->callingpres;
09832    tmp->caller.id.number.plan = i->cid_ton;
09833    tmp->caller.ani2 = i->cid_ani2;
09834    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09835    /* clear the fake event in case we posted one before we had ast_channel */
09836    i->fake_event = 0;
09837    /* Assure there is no confmute on this channel */
09838    dahdi_confmute(i, 0);
09839    i->muting = 0;
09840    /* Configure the new channel jb */
09841    ast_jb_configure(tmp, &global_jbconf);
09842 
09843    /* Set initial device state */
09844    ast_copy_string(device_name, tmp->name, sizeof(device_name));
09845    dashptr = strrchr(device_name, '-');
09846    if (dashptr) {
09847       *dashptr = '\0';
09848    }
09849    tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE;
09850    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
09851 
09852    for (v = i->vars ; v ; v = v->next)
09853       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09854 
09855    ast_module_ref(ast_module_info->self);
09856 
09857    dahdi_ami_channel_event(i, tmp);
09858    if (startpbx) {
09859 #ifdef HAVE_OPENR2
09860       if (i->mfcr2call) {
09861          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09862       }
09863 #endif
09864       if (ast_pbx_start(tmp)) {
09865          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09866          ast_hangup(tmp);
09867          return NULL;
09868       }
09869    }
09870    return tmp;
09871 }

static int dahdi_open ( char *  fn  )  [static]

Definition at line 4369 of file chan_dahdi.c.

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

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

04370 {
04371    int fd;
04372    int isnum;
04373    int chan = 0;
04374    int bs;
04375    int x;
04376    isnum = 1;
04377    for (x = 0; x < strlen(fn); x++) {
04378       if (!isdigit(fn[x])) {
04379          isnum = 0;
04380          break;
04381       }
04382    }
04383    if (isnum) {
04384       chan = atoi(fn);
04385       if (chan < 1) {
04386          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04387          return -1;
04388       }
04389       fn = "/dev/dahdi/channel";
04390    }
04391    fd = open(fn, O_RDWR | O_NONBLOCK);
04392    if (fd < 0) {
04393       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04394       return -1;
04395    }
04396    if (chan) {
04397       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04398          x = errno;
04399          close(fd);
04400          errno = x;
04401          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04402          return -1;
04403       }
04404    }
04405    bs = READ_SIZE;
04406    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04407       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04408       x = errno;
04409       close(fd);
04410       errno = x;
04411       return -1;
04412    }
04413    return fd;
04414 }

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

Definition at line 6708 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_sig_pri_lib_handles(), DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, errno, dahdi_pvt::ignoredtmf, dahdi_pvt::sig, and ast_channel::tech_pvt.

06709 {
06710    char *cp;
06711    struct dahdi_pvt *p = chan->tech_pvt;
06712 
06713    /* all supported options require data */
06714    if (!p || !data || (*datalen < 1)) {
06715       errno = EINVAL;
06716       return -1;
06717    }
06718 
06719    switch (option) {
06720    case AST_OPTION_DIGIT_DETECT:
06721       cp = (char *) data;
06722       *cp = p->ignoredtmf ? 0 : 1;
06723       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06724       break;
06725    case AST_OPTION_FAX_DETECT:
06726       cp = (char *) data;
06727       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06728       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06729       break;
06730    case AST_OPTION_CC_AGENT_TYPE:
06731 #if defined(HAVE_PRI)
06732 #if defined(HAVE_PRI_CCSS)
06733       if (dahdi_sig_pri_lib_handles(p->sig)) {
06734          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06735          break;
06736       }
06737 #endif   /* defined(HAVE_PRI_CCSS) */
06738 #endif   /* defined(HAVE_PRI) */
06739       return -1;
06740    default:
06741       return -1;
06742    }
06743 
06744    errno = 0;
06745 
06746    return 0;
06747 }

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

Definition at line 3857 of file chan_dahdi.c.

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

Referenced by action_dahdidialoffhook().

03858 {
03859    for (;;) {
03860       if (p->owner) {
03861          if (ast_channel_trylock(p->owner)) {
03862             DEADLOCK_AVOIDANCE(&p->lock);
03863          } else {
03864             ast_queue_frame(p->owner, f);
03865             ast_channel_unlock(p->owner);
03866             break;
03867          }
03868       } else
03869          break;
03870    }
03871 }

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

Definition at line 8956 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_frfree, 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, dahdi_pvt::fake_event, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_subchannel::inthreeway, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, mute, dahdi_pvt::muting, 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, dahdi_pvt::owner, ast_frame::ptr, dahdi_pvt::pulsedial, 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.

08957 {
08958    struct dahdi_pvt *p;
08959    int res;
08960    int idx;
08961    void *readbuf;
08962    struct ast_frame *f;
08963 
08964    /*
08965     * For analog channels, we must do deadlock avoidance because
08966     * analog ports can have more than one Asterisk channel using
08967     * the same private structure.
08968     */
08969    p = ast->tech_pvt;
08970    while (ast_mutex_trylock(&p->lock)) {
08971       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08972 
08973       /*
08974        * Check to see if the channel is still associated with the same
08975        * private structure.  While the Asterisk channel was unlocked
08976        * the following events may have occured:
08977        *
08978        * 1) A masquerade may have associated the channel with another
08979        * technology or private structure.
08980        *
08981        * 2) For PRI calls, call signaling could change the channel
08982        * association to another B channel (private structure).
08983        */
08984       if (ast->tech_pvt != p) {
08985          /* The channel is no longer associated.  Quit gracefully. */
08986          return &ast_null_frame;
08987       }
08988    }
08989 
08990    idx = dahdi_get_index(ast, p, 0);
08991 
08992    /* Hang up if we don't really exist */
08993    if (idx < 0)   {
08994       ast_log(LOG_WARNING, "We don't exist?\n");
08995       ast_mutex_unlock(&p->lock);
08996       return NULL;
08997    }
08998 
08999    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
09000       ast_mutex_unlock(&p->lock);
09001       return NULL;
09002    }
09003 
09004    p->subs[idx].f.frametype = AST_FRAME_NULL;
09005    p->subs[idx].f.datalen = 0;
09006    p->subs[idx].f.samples = 0;
09007    p->subs[idx].f.mallocd = 0;
09008    p->subs[idx].f.offset = 0;
09009    p->subs[idx].f.subclass.integer = 0;
09010    p->subs[idx].f.delivery = ast_tv(0,0);
09011    p->subs[idx].f.src = "dahdi_read";
09012    p->subs[idx].f.data.ptr = NULL;
09013 
09014    /* make sure it sends initial key state as first frame */
09015    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
09016    {
09017       struct dahdi_params ps;
09018 
09019       memset(&ps, 0, sizeof(ps));
09020       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
09021          ast_mutex_unlock(&p->lock);
09022          return NULL;
09023       }
09024       p->firstradio = 1;
09025       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09026       if (ps.rxisoffhook)
09027       {
09028          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09029       }
09030       else
09031       {
09032          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09033       }
09034       ast_mutex_unlock(&p->lock);
09035       return &p->subs[idx].f;
09036    }
09037    if (p->ringt > 0) {
09038       if (!(--p->ringt)) {
09039          ast_mutex_unlock(&p->lock);
09040          return NULL;
09041       }
09042    }
09043 
09044 #ifdef HAVE_OPENR2
09045    if (p->mfcr2) {
09046       openr2_chan_process_event(p->r2chan);
09047       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09048          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09049          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
09050           * now enqueue a progress frame to bridge the media up */
09051          if (p->mfcr2_call_accepted &&
09052              !p->mfcr2_progress && 
09053              ast->_state == AST_STATE_RINGING) {
09054             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09055             ast_queue_frame(p->owner, &f);
09056             p->mfcr2_progress = 1;
09057          }
09058       }
09059    }
09060 #endif
09061 
09062    if (p->subs[idx].needringing) {
09063       /* Send ringing frame if requested */
09064       p->subs[idx].needringing = 0;
09065       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09066       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09067       ast_setstate(ast, AST_STATE_RINGING);
09068       ast_mutex_unlock(&p->lock);
09069       return &p->subs[idx].f;
09070    }
09071 
09072    if (p->subs[idx].needbusy) {
09073       /* Send busy frame if requested */
09074       p->subs[idx].needbusy = 0;
09075       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09076       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09077       ast_mutex_unlock(&p->lock);
09078       return &p->subs[idx].f;
09079    }
09080 
09081    if (p->subs[idx].needcongestion) {
09082       /* Send congestion frame if requested */
09083       p->subs[idx].needcongestion = 0;
09084       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09085       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09086       ast_mutex_unlock(&p->lock);
09087       return &p->subs[idx].f;
09088    }
09089 
09090    if (p->subs[idx].needanswer) {
09091       /* Send answer frame if requested */
09092       p->subs[idx].needanswer = 0;
09093       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09094       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09095       ast_mutex_unlock(&p->lock);
09096       return &p->subs[idx].f;
09097    }
09098 #ifdef HAVE_OPENR2
09099    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09100       /* openr2 took care of reading and handling any event
09101         (needanswer, needbusy etc), if we continue we will read()
09102         twice, lets just return a null frame. This should only
09103         happen when openr2 is dialing out */
09104       ast_mutex_unlock(&p->lock);
09105       return &ast_null_frame;
09106    }
09107 #endif
09108 
09109    if (p->subs[idx].needflash) {
09110       /* Send answer frame if requested */
09111       p->subs[idx].needflash = 0;
09112       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09113       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09114       ast_mutex_unlock(&p->lock);
09115       return &p->subs[idx].f;
09116    }
09117 
09118    if (p->subs[idx].needhold) {
09119       /* Send answer frame if requested */
09120       p->subs[idx].needhold = 0;
09121       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09122       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09123       ast_mutex_unlock(&p->lock);
09124       ast_debug(1, "Sending hold on '%s'\n", ast->name);
09125       return &p->subs[idx].f;
09126    }
09127 
09128    if (p->subs[idx].needunhold) {
09129       /* Send answer frame if requested */
09130       p->subs[idx].needunhold = 0;
09131       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09132       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09133       ast_mutex_unlock(&p->lock);
09134       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09135       return &p->subs[idx].f;
09136    }
09137 
09138    /*
09139     * If we have a fake_event, fake an exception to handle it only
09140     * if this channel owns the private.
09141     */
09142    if (p->fake_event && p->owner == ast) {
09143       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09144          struct analog_pvt *analog_p = p->sig_pvt;
09145 
09146          f = analog_exception(analog_p, ast);
09147       } else {
09148          f = __dahdi_exception(ast);
09149       }
09150       ast_mutex_unlock(&p->lock);
09151       return f;
09152    }
09153 
09154    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09155       if (!p->subs[idx].linear) {
09156          p->subs[idx].linear = 1;
09157          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09158          if (res)
09159             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09160       }
09161    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09162       (ast->rawreadformat == AST_FORMAT_ALAW)) {
09163       if (p->subs[idx].linear) {
09164          p->subs[idx].linear = 0;
09165          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09166          if (res)
09167             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09168       }
09169    } else {
09170       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09171       ast_mutex_unlock(&p->lock);
09172       return NULL;
09173    }
09174    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09175    CHECK_BLOCKING(ast);
09176    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09177    ast_clear_flag(ast, AST_FLAG_BLOCKING);
09178    /* Check for hangup */
09179    if (res < 0) {
09180       f = NULL;
09181       if (res == -1) {
09182          if (errno == EAGAIN) {
09183             /* Return "NULL" frame if there is nobody there */
09184             ast_mutex_unlock(&p->lock);
09185             return &p->subs[idx].f;
09186          } else if (errno == ELAST) {
09187             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09188                struct analog_pvt *analog_p = p->sig_pvt;
09189                f = analog_exception(analog_p, ast);
09190             } else {
09191                f = __dahdi_exception(ast);
09192             }
09193          } else
09194             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09195       }
09196       ast_mutex_unlock(&p->lock);
09197       return f;
09198    }
09199    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09200       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09201       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09202          struct analog_pvt *analog_p = p->sig_pvt;
09203          f = analog_exception(analog_p, ast);
09204       } else {
09205          f = __dahdi_exception(ast);
09206       }
09207       ast_mutex_unlock(&p->lock);
09208       return f;
09209    }
09210    if (p->tdd) { /* if in TDD mode, see if we receive that */
09211       int c;
09212 
09213       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09214       if (c < 0) {
09215          ast_debug(1,"tdd_feed failed\n");
09216          ast_mutex_unlock(&p->lock);
09217          return NULL;
09218       }
09219       if (c) { /* if a char to return */
09220          p->subs[idx].f.subclass.integer = 0;
09221          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09222          p->subs[idx].f.mallocd = 0;
09223          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09224          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09225          p->subs[idx].f.datalen = 1;
09226          *((char *) p->subs[idx].f.data.ptr) = c;
09227          ast_mutex_unlock(&p->lock);
09228          return &p->subs[idx].f;
09229       }
09230    }
09231    if (idx == SUB_REAL) {
09232       /* Ensure the CW timers decrement only on a single subchannel */
09233       if (p->cidcwexpire) {
09234          if (!--p->cidcwexpire) {
09235             /* Expired CID/CW */
09236             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09237             restore_conference(p);
09238          }
09239       }
09240       if (p->cid_suppress_expire) {
09241          --p->cid_suppress_expire;
09242       }
09243       if (p->callwaitingrepeat) {
09244          if (!--p->callwaitingrepeat) {
09245             /* Expired, Repeat callwaiting tone */
09246             ++p->callwaitrings;
09247             dahdi_callwait(ast);
09248          }
09249       }
09250    }
09251    if (p->subs[idx].linear) {
09252       p->subs[idx].f.datalen = READ_SIZE * 2;
09253    } else
09254       p->subs[idx].f.datalen = READ_SIZE;
09255 
09256    /* Handle CallerID Transmission */
09257    if ((p->owner == ast) && p->cidspill) {
09258       send_callerid(p);
09259    }
09260 
09261    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09262    p->subs[idx].f.subclass.codec = ast->rawreadformat;
09263    p->subs[idx].f.samples = READ_SIZE;
09264    p->subs[idx].f.mallocd = 0;
09265    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09266    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09267 #if 0
09268    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09269 #endif
09270    if ((p->dialing && !p->waitingfordt.tv_sec) ||  p->radio || /* Transmitting something */
09271       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09272       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09273       ) {
09274       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09275          don't send anything */
09276       p->subs[idx].f.frametype = AST_FRAME_NULL;
09277       p->subs[idx].f.subclass.integer = 0;
09278       p->subs[idx].f.samples = 0;
09279       p->subs[idx].f.mallocd = 0;
09280       p->subs[idx].f.offset = 0;
09281       p->subs[idx].f.data.ptr = NULL;
09282       p->subs[idx].f.datalen= 0;
09283    }
09284    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09285       /* Perform busy detection etc on the dahdi line */
09286       int mute;
09287 
09288       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09289 
09290       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09291       mute = ast_dsp_was_muted(p->dsp);
09292       if (p->muting != mute) {
09293          p->muting = mute;
09294          dahdi_confmute(p, mute);
09295       }
09296 
09297       if (f) {
09298          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09299             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09300                /* Treat this as a "hangup" instead of a "busy" on the assumption that
09301                   a busy */
09302                ast_frfree(f);
09303                f = NULL;
09304             }
09305          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09306             || f->frametype == AST_FRAME_DTMF_END) {
09307 #ifdef HAVE_PRI
09308             if (dahdi_sig_pri_lib_handles(p->sig)
09309                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09310                && p->pri
09311                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09312                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09313                /* Don't accept in-band DTMF when in overlap dial mode */
09314                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09315                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09316                   (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
09317 
09318                f->frametype = AST_FRAME_NULL;
09319                f->subclass.integer = 0;
09320             }
09321 #endif
09322             /* DSP clears us of being pulse */
09323             p->pulsedial = 0;
09324          } else if (p->waitingfordt.tv_sec) {
09325             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09326                p->waitingfordt.tv_sec = 0;
09327                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09328                ast_frfree(f);
09329                f = NULL;
09330             } else if (f->frametype == AST_FRAME_VOICE) {
09331                f->frametype = AST_FRAME_NULL;
09332                f->subclass.integer = 0;
09333                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) {
09334                   p->waitingfordt.tv_sec = 0;
09335                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09336                   ast_dsp_set_features(p->dsp, p->dsp_features);
09337                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09338                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09339                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09340                      if (res < 0) {
09341                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09342                         p->dop.dialstr[0] = '\0';
09343                         ast_mutex_unlock(&p->lock);
09344                         ast_frfree(f);
09345                         return NULL;
09346                      } else {
09347                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09348                         p->dialing = 1;
09349                         p->dop.dialstr[0] = '\0';
09350                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09351                         ast_setstate(ast, AST_STATE_DIALING);
09352                      }
09353                   }
09354                }
09355             }
09356          }
09357       }
09358    } else
09359       f = &p->subs[idx].f;
09360 
09361    if (f) {
09362       switch (f->frametype) {
09363       case AST_FRAME_DTMF_BEGIN:
09364       case AST_FRAME_DTMF_END:
09365          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09366             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09367          } else {
09368             dahdi_handle_dtmf(ast, idx, &f);
09369          }
09370          break;
09371       case AST_FRAME_VOICE:
09372          if (p->cidspill || p->cid_suppress_expire) {
09373             /* We are/were sending a caller id spill.  Suppress any echo. */
09374             p->subs[idx].f.frametype = AST_FRAME_NULL;
09375             p->subs[idx].f.subclass.integer = 0;
09376             p->subs[idx].f.samples = 0;
09377             p->subs[idx].f.mallocd = 0;
09378             p->subs[idx].f.offset = 0;
09379             p->subs[idx].f.data.ptr = NULL;
09380             p->subs[idx].f.datalen= 0;
09381          }
09382          break;
09383       default:
09384          break;
09385       }
09386    }
09387 
09388    ast_mutex_unlock(&p->lock);
09389    return f;
09390 }

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

Definition at line 13721 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, is_group_or_channel_match(), dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::next, dahdi_pvt::oprmode, dahdi_starting_point::opt, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::radio, restart_monitor(), 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.

13722 {
13723    int callwait = 0;
13724    struct dahdi_pvt *p;
13725    struct ast_channel *tmp = NULL;
13726    struct dahdi_pvt *exitpvt;
13727    int channelmatched = 0;
13728    int groupmatched = 0;
13729 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13730    int transcapdigital = 0;
13731 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13732    struct dahdi_starting_point start;
13733 
13734    ast_mutex_lock(&iflock);
13735    p = determine_starting_point(data, &start);
13736    if (!p) {
13737       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13738       ast_mutex_unlock(&iflock);
13739       return NULL;
13740    }
13741 
13742    /* Search for an unowned channel */
13743    exitpvt = p;
13744    while (p && !tmp) {
13745       if (start.roundrobin)
13746          round_robin[start.rr_starting_point] = p;
13747 
13748       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13749          && available(&p, channelmatched)) {
13750          ast_debug(1, "Using channel %d\n", p->channel);
13751 
13752          callwait = (p->owner != NULL);
13753 #ifdef HAVE_OPENR2
13754          if (p->mfcr2) {
13755             ast_mutex_lock(&p->lock);
13756             if (p->mfcr2call) {
13757                ast_mutex_unlock(&p->lock);
13758                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13759                goto next;
13760             }
13761             p->mfcr2call = 1;
13762             ast_mutex_unlock(&p->lock);
13763          }
13764 #endif
13765          if (p->channel == CHAN_PSEUDO) {
13766             p = duplicate_pseudo(p);
13767             if (!p) {
13768                break;
13769             }
13770          }
13771 
13772          p->distinctivering = 0;
13773          /* Make special notes */
13774          switch (start.opt) {
13775          case '\0':
13776             /* No option present. */
13777             break;
13778          case 'c':
13779             /* Confirm answer */
13780             p->confirmanswer = 1;
13781             break;
13782          case 'r':
13783             /* Distinctive ring */
13784             p->distinctivering = start.cadance;
13785             break;
13786          case 'd':
13787 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13788             /* If this is an ISDN call, make it digital */
13789             transcapdigital = AST_TRANS_CAP_DIGITAL;
13790 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13791             break;
13792          default:
13793             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13794             break;
13795          }
13796 
13797          p->outgoing = 1;
13798          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13799             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13800 #ifdef HAVE_PRI
13801          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13802             /*
13803              * We already have the B channel reserved for this call.  We
13804              * just need to make sure that dahdi_hangup() has completed
13805              * cleaning up before continuing.
13806              */
13807             ast_mutex_lock(&p->lock);
13808             ast_mutex_unlock(&p->lock);
13809 
13810             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13811                sizeof(p->dnid));
13812             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13813 #endif
13814 #if defined(HAVE_SS7)
13815          } else if (p->sig == SIG_SS7) {
13816             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13817 #endif   /* defined(HAVE_SS7) */
13818          } else {
13819             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13820          }
13821          if (!tmp) {
13822             p->outgoing = 0;
13823 #if defined(HAVE_PRI)
13824             switch (p->sig) {
13825             case SIG_PRI_LIB_HANDLE_CASES:
13826 #if defined(HAVE_PRI_CALL_WAITING)
13827                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13828                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13829                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13830                }
13831 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13832                /*
13833                 * This should be the last thing to clear when we are done with
13834                 * the channel.
13835                 */
13836                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13837                break;
13838             default:
13839                break;
13840             }
13841 #endif   /* defined(HAVE_PRI) */
13842          } else {
13843             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13844          }
13845          break;
13846       }
13847 #ifdef HAVE_OPENR2
13848 next:
13849 #endif
13850       if (start.backwards) {
13851          p = p->prev;
13852          if (!p)
13853             p = ifend;
13854       } else {
13855          p = p->next;
13856          if (!p)
13857             p = iflist;
13858       }
13859       /* stop when you roll to the one that we started from */
13860       if (p == exitpvt)
13861          break;
13862    }
13863    ast_mutex_unlock(&iflock);
13864    restart_monitor();
13865    if (cause && !tmp) {
13866       if (callwait || channelmatched) {
13867          *cause = AST_CAUSE_BUSY;
13868       } else if (groupmatched) {
13869          *cause = AST_CAUSE_CONGESTION;
13870       } else {
13871          /*
13872           * We did not match any channel requested.
13873           * Dialplan error requesting non-existant channel?
13874           */
13875       }
13876    }
13877 
13878    return tmp;
13879 }

static int dahdi_restart ( void   )  [static]

Definition at line 15244 of file chan_dahdi.c.

References ast_active_channels(), ast_cond_wait, ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_verb, dahdi_softhangup_all(), destroy_all_channels(), dahdi_subchannel::dfd, LOG_WARNING, sig_pri_span::master, dahdi_pvt::next, dahdi_pvt::owner, setup_dahdi(), sig_pri_init_pri(), sig_ss7_init_linkset(), SIG_SS7_NUM_DCHANS, SUB_REAL, and dahdi_pvt::subs.

Referenced by action_dahdirestart(), and dahdi_restart_cmd().

15245 {
15246 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15247    int i, j;
15248 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15249    int cancel_code;
15250    struct dahdi_pvt *p;
15251 
15252    ast_mutex_lock(&restart_lock);
15253    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15254    dahdi_softhangup_all();
15255    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15256 #ifdef HAVE_OPENR2
15257    dahdi_r2_destroy_links();
15258 #endif
15259 
15260 #if defined(HAVE_PRI)
15261    for (i = 0; i < NUM_SPANS; i++) {
15262       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15263          cancel_code = pthread_cancel(pris[i].pri.master);
15264          pthread_kill(pris[i].pri.master, SIGURG);
15265          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);
15266          pthread_join(pris[i].pri.master, NULL);
15267          ast_debug(4, "Joined thread of span %d\n", i);
15268       }
15269    }
15270 #endif
15271 
15272 #if defined(HAVE_SS7)
15273    for (i = 0; i < NUM_SPANS; i++) {
15274       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15275          cancel_code = pthread_cancel(linksets[i].ss7.master);
15276          pthread_kill(linksets[i].ss7.master, SIGURG);
15277          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);
15278          pthread_join(linksets[i].ss7.master, NULL);
15279          ast_debug(4, "Joined thread of span %d\n", i);
15280       }
15281    }
15282 #endif   /* defined(HAVE_SS7) */
15283 
15284    ast_mutex_lock(&monlock);
15285    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15286       cancel_code = pthread_cancel(monitor_thread);
15287       pthread_kill(monitor_thread, SIGURG);
15288       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15289       pthread_join(monitor_thread, NULL);
15290       ast_debug(4, "Joined monitor thread\n");
15291    }
15292    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15293 
15294    ast_mutex_lock(&ss_thread_lock);
15295    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15296       int x = DAHDI_FLASH;
15297       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15298 
15299       ast_mutex_lock(&iflock);
15300       for (p = iflist; p; p = p->next) {
15301          if (p->owner) {
15302             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15303             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15304          }
15305       }
15306       ast_mutex_unlock(&iflock);
15307       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15308    }
15309 
15310    /* ensure any created channels before monitor threads were stopped are hungup */
15311    dahdi_softhangup_all();
15312    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15313    destroy_all_channels();
15314    memset(round_robin, 0, sizeof(round_robin));
15315    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15316 
15317    ast_mutex_unlock(&monlock);
15318 
15319 #ifdef HAVE_PRI
15320    for (i = 0; i < NUM_SPANS; i++) {
15321       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15322          dahdi_close_pri_fd(&(pris[i]), j);
15323    }
15324 
15325    memset(pris, 0, sizeof(pris));
15326    for (i = 0; i < NUM_SPANS; i++) {
15327       sig_pri_init_pri(&pris[i].pri);
15328    }
15329    pri_set_error(dahdi_pri_error);
15330    pri_set_message(dahdi_pri_message);
15331 #endif
15332 #if defined(HAVE_SS7)
15333    for (i = 0; i < NUM_SPANS; i++) {
15334       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15335          dahdi_close_ss7_fd(&(linksets[i]), j);
15336    }
15337 
15338    memset(linksets, 0, sizeof(linksets));
15339    for (i = 0; i < NUM_SPANS; i++) {
15340       sig_ss7_init_linkset(&linksets[i].ss7);
15341    }
15342    ss7_set_error(dahdi_ss7_error);
15343    ss7_set_message(dahdi_ss7_message);
15344 #endif   /* defined(HAVE_SS7) */
15345 
15346    if (setup_dahdi(2) != 0) {
15347       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15348       ast_mutex_unlock(&ss_thread_lock);
15349       return 1;
15350    }
15351    ast_mutex_unlock(&ss_thread_lock);
15352    ast_mutex_unlock(&restart_lock);
15353    return 0;
15354 }

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

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

15357 {
15358    switch (cmd) {
15359    case CLI_INIT:
15360       e->command = "dahdi restart";
15361       e->usage =
15362          "Usage: dahdi restart\n"
15363          "  Restarts the DAHDI channels: destroys them all and then\n"
15364          "  re-reads them from chan_dahdi.conf.\n"
15365          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15366          "";
15367       return NULL;
15368    case CLI_GENERATE:
15369       return NULL;
15370    }
15371    if (a->argc != 2)
15372       return CLI_SHOWUSAGE;
15373 
15374    if (dahdi_restart() != 0)
15375       return CLI_FAILURE;
15376    return CLI_SUCCESS;
15377 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

Definition at line 7653 of file chan_dahdi.c.

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

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

07654 {
07655    int x;
07656    int res;
07657    /* Make sure our transmit state is on hook */
07658    x = 0;
07659    x = DAHDI_ONHOOK;
07660    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07661    do {
07662       x = DAHDI_RING;
07663       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07664       if (res) {
07665          switch (errno) {
07666          case EBUSY:
07667          case EINTR:
07668             /* Wait just in case */
07669             usleep(10000);
07670             continue;
07671          case EINPROGRESS:
07672             res = 0;
07673             break;
07674          default:
07675             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07676             res = 0;
07677          }
07678       }
07679    } while (res);
07680    return res;
07681 }

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

Definition at line 18837 of file chan_dahdi.c.

References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_debug, ast_free, AST_LAW, ast_log(), ast_malloc, dahdi_pvt::channel, dahdi_get_index, dahdi_subchannel::dfd, END_SILENCE_LEN, errno, HEADER_LEN, HEADER_MS, len(), LOG_ERROR, LOG_WARNING, dahdi_pvt::mate, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.

18838 {
18839 #define  END_SILENCE_LEN 400
18840 #define  HEADER_MS 50
18841 #define  TRAILER_MS 5
18842 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18843 #define  ASCII_BYTES_PER_CHAR 80
18844 
18845    unsigned char *buf,*mybuf;
18846    struct dahdi_pvt *p = c->tech_pvt;
18847    struct pollfd fds[1];
18848    int size,res,fd,len,x;
18849    int bytes=0;
18850    /* Initial carrier (imaginary) */
18851    float cr = 1.0;
18852    float ci = 0.0;
18853    float scont = 0.0;
18854    int idx;
18855 
18856    idx = dahdi_get_index(c, p, 0);
18857    if (idx < 0) {
18858       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18859       return -1;
18860    }
18861    if (!text[0]) return(0); /* if nothing to send, don't */
18862    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18863    if (p->mate)
18864       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18865    else
18866       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18867    if (!buf)
18868       return -1;
18869    mybuf = buf;
18870    if (p->mate) {
18871       int codec = AST_LAW(p);
18872       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18873          PUT_CLID_MARKMS;
18874       }
18875       /* Put actual message */
18876       for (x = 0; text[x]; x++) {
18877          PUT_CLID(text[x]);
18878       }
18879       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18880          PUT_CLID_MARKMS;
18881       }
18882       len = bytes;
18883       buf = mybuf;
18884    } else {
18885       len = tdd_generate(p->tdd, buf, text);
18886       if (len < 1) {
18887          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18888          ast_free(mybuf);
18889          return -1;
18890       }
18891    }
18892    memset(buf + len, 0x7f, END_SILENCE_LEN);
18893    len += END_SILENCE_LEN;
18894    fd = p->subs[idx].dfd;
18895    while (len) {
18896       if (ast_check_hangup(c)) {
18897          ast_free(mybuf);
18898          return -1;
18899       }
18900       size = len;
18901       if (size > READ_SIZE)
18902          size = READ_SIZE;
18903       fds[0].fd = fd;
18904       fds[0].events = POLLOUT | POLLPRI;
18905       fds[0].revents = 0;
18906       res = poll(fds, 1, -1);
18907       if (!res) {
18908          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18909          continue;
18910       }
18911       /* if got exception */
18912       if (fds[0].revents & POLLPRI) {
18913          ast_free(mybuf);
18914          return -1;
18915       }
18916       if (!(fds[0].revents & POLLOUT)) {
18917          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18918          continue;
18919       }
18920       res = write(fd, buf, size);
18921       if (res != size) {
18922          if (res == -1) {
18923             ast_free(mybuf);
18924             return -1;
18925          }
18926          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18927          break;
18928       }
18929       len -= size;
18930       buf += size;
18931    }
18932    ast_free(mybuf);
18933    return(0);
18934 }

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

Definition at line 15985 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, dahdi_pvt::next, and ast_cli_entry::usage.

15986 {
15987    int channel;
15988    int on;
15989    struct dahdi_pvt *dahdi_chan = NULL;
15990 
15991    switch (cmd) {
15992    case CLI_INIT:
15993       e->command = "dahdi set dnd";
15994       e->usage =
15995          "Usage: dahdi set dnd <chan#> <on|off>\n"
15996          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15997          "  Changes take effect immediately.\n"
15998          "  <chan num> is the channel number\n"
15999          "  <on|off> Enable or disable DND mode?\n"
16000          ;
16001       return NULL;
16002    case CLI_GENERATE:
16003       return NULL;
16004    }
16005 
16006    if (a->argc != 5)
16007       return CLI_SHOWUSAGE;
16008 
16009    if ((channel = atoi(a->argv[3])) <= 0) {
16010       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16011       return CLI_SHOWUSAGE;
16012    }
16013 
16014    if (ast_true(a->argv[4]))
16015       on = 1;
16016    else if (ast_false(a->argv[4]))
16017       on = 0;
16018    else {
16019       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16020       return CLI_SHOWUSAGE;
16021    }
16022 
16023    ast_mutex_lock(&iflock);
16024    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16025       if (dahdi_chan->channel != channel)
16026          continue;
16027 
16028       /* Found the channel. Actually set it */
16029       dahdi_dnd(dahdi_chan, on);
16030       break;
16031    }
16032    ast_mutex_unlock(&iflock);
16033 
16034    if (!dahdi_chan) {
16035       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16036       return CLI_FAILURE;
16037    }
16038 
16039    return CLI_SUCCESS;
16040 }

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

Definition at line 5191 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(), mkintf(), mwi_send_process_buffer(), mwi_send_process_event(), my_off_hook(), and my_on_hook().

05192 {
05193    int x, res;
05194 
05195    x = hs;
05196    res = ioctl(fd, DAHDI_HOOK, &x);
05197 
05198    if (res < 0) {
05199       if (errno == EINPROGRESS)
05200          return 0;
05201       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05202       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05203    }
05204 
05205    return res;
05206 }

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

Definition at line 15833 of file chan_dahdi.c.

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

15834 {
15835    int channel;
15836    int gain;
15837    int tx;
15838    struct dahdi_hwgain hwgain;
15839    struct dahdi_pvt *tmp = NULL;
15840 
15841    switch (cmd) {
15842    case CLI_INIT:
15843       e->command = "dahdi set hwgain {rx|tx}";
15844       e->usage =
15845          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15846          "   Sets the hardware gain on a given channel.  Changes take effect\n"
15847          "   immediately whether the channel is in use or not.\n"
15848          "\n"
15849          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15850          "   <chan num> is the channel number relative to the device\n"
15851          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
15852          "\n"
15853          "   Please note:\n"
15854          "   * This is currently the only way to set hwgain by the channel driver.\n"
15855          "   * hwgain is only supportable by hardware with analog ports because\n"
15856          "     hwgain works on the analog side of an analog-digital conversion.\n";
15857       return NULL;
15858    case CLI_GENERATE:
15859       return NULL;
15860    }
15861 
15862    if (a->argc != 6)
15863       return CLI_SHOWUSAGE;
15864 
15865    if (!strcasecmp("rx", a->argv[3]))
15866       tx = 0; /* rx */
15867    else if (!strcasecmp("tx", a->argv[3]))
15868       tx = 1; /* tx */
15869    else
15870       return CLI_SHOWUSAGE;
15871 
15872    channel = atoi(a->argv[4]);
15873    gain = atof(a->argv[5])*10.0;
15874 
15875    ast_mutex_lock(&iflock);
15876 
15877    for (tmp = iflist; tmp; tmp = tmp->next) {
15878 
15879       if (tmp->channel != channel)
15880          continue;
15881 
15882       if (tmp->subs[SUB_REAL].dfd == -1)
15883          break;
15884 
15885       hwgain.newgain = gain;
15886       hwgain.tx = tx;
15887       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15888          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15889          ast_mutex_unlock(&iflock);
15890          return CLI_FAILURE;
15891       }
15892       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15893          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15894       break;
15895    }
15896 
15897    ast_mutex_unlock(&iflock);
15898 
15899    if (tmp)
15900       return CLI_SUCCESS;
15901 
15902    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15903    return CLI_FAILURE;
15904 
15905 }

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

Definition at line 15907 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_subchannel::dfd, ast_cli_args::fd, dahdi_pvt::law, dahdi_pvt::next, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::txdrc, dahdi_pvt::txgain, and ast_cli_entry::usage.

15908 {
15909    int channel;
15910    float gain;
15911    int tx;
15912    int res;
15913    struct dahdi_pvt *tmp = NULL;
15914 
15915    switch (cmd) {
15916    case CLI_INIT:
15917       e->command = "dahdi set swgain {rx|tx}";
15918       e->usage =
15919          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15920          "   Sets the software gain on a given channel and overrides the\n"
15921          "   value provided at module loadtime.  Changes take effect\n"
15922          "   immediately whether the channel is in use or not.\n"
15923          "\n"
15924          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15925          "   <chan num> is the channel number relative to the device\n"
15926          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15927       return NULL;
15928    case CLI_GENERATE:
15929       return NULL;
15930    }
15931 
15932    if (a->argc != 6)
15933       return CLI_SHOWUSAGE;
15934 
15935    if (!strcasecmp("rx", a->argv[3]))
15936       tx = 0; /* rx */
15937    else if (!strcasecmp("tx", a->argv[3]))
15938       tx = 1; /* tx */
15939    else
15940       return CLI_SHOWUSAGE;
15941 
15942    channel = atoi(a->argv[4]);
15943    gain = atof(a->argv[5]);
15944 
15945    ast_mutex_lock(&iflock);
15946    for (tmp = iflist; tmp; tmp = tmp->next) {
15947 
15948       if (tmp->channel != channel)
15949          continue;
15950 
15951       if (tmp->subs[SUB_REAL].dfd == -1)
15952          break;
15953 
15954       if (tx)
15955          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15956       else
15957          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15958 
15959       if (res) {
15960          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15961          ast_mutex_unlock(&iflock);
15962          return CLI_FAILURE;
15963       }
15964 
15965       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15966          tx ? "tx" : "rx", gain, channel);
15967 
15968       if (tx) {
15969          tmp->txgain = gain;
15970       } else {
15971          tmp->rxgain = gain;
15972       }
15973       break;
15974    }
15975    ast_mutex_unlock(&iflock);
15976 
15977    if (tmp)
15978       return CLI_SUCCESS;
15979 
15980    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15981    return CLI_FAILURE;
15982 
15983 }

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

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

Definition at line 6749 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, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, oprmode::peer, 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.

06750 {
06751    char *cp;
06752    signed char *scp;
06753    int x;
06754    int idx;
06755    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06756    struct oprmode *oprmode;
06757 
06758 
06759    /* all supported options require data */
06760    if (!p || !data || (datalen < 1)) {
06761       errno = EINVAL;
06762       return -1;
06763    }
06764 
06765    switch (option) {
06766    case AST_OPTION_TXGAIN:
06767       scp = (signed char *) data;
06768       idx = dahdi_get_index(chan, p, 0);
06769       if (idx < 0) {
06770          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06771          return -1;
06772       }
06773       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06774       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06775    case AST_OPTION_RXGAIN:
06776       scp = (signed char *) data;
06777       idx = dahdi_get_index(chan, p, 0);
06778       if (idx < 0) {
06779          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06780          return -1;
06781       }
06782       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06783       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06784    case AST_OPTION_TONE_VERIFY:
06785       if (!p->dsp)
06786          break;
06787       cp = (char *) data;
06788       switch (*cp) {
06789       case 1:
06790          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06791          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06792          break;
06793       case 2:
06794          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06795          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06796          break;
06797       default:
06798          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06799          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06800          break;
06801       }
06802       break;
06803    case AST_OPTION_TDD:
06804       /* turn on or off TDD */
06805       cp = (char *) data;
06806       p->mate = 0;
06807       if (!*cp) { /* turn it off */
06808          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06809          if (p->tdd)
06810             tdd_free(p->tdd);
06811          p->tdd = 0;
06812          break;
06813       }
06814       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06815          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06816       dahdi_disable_ec(p);
06817       /* otherwise, turn it on */
06818       if (!p->didtdd) { /* if havent done it yet */
06819          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06820          unsigned char *buf;
06821          int size, res, fd, len;
06822          struct pollfd fds[1];
06823 
06824          buf = mybuf;
06825          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06826          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06827          len = 40000;
06828          idx = dahdi_get_index(chan, p, 0);
06829          if (idx < 0) {
06830             ast_log(LOG_WARNING, "No index in TDD?\n");
06831             return -1;
06832          }
06833          fd = p->subs[idx].dfd;
06834          while (len) {
06835             if (ast_check_hangup(chan))
06836                return -1;
06837             size = len;
06838             if (size > READ_SIZE)
06839                size = READ_SIZE;
06840             fds[0].fd = fd;
06841             fds[0].events = POLLPRI | POLLOUT;
06842             fds[0].revents = 0;
06843             res = poll(fds, 1, -1);
06844             if (!res) {
06845                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06846                continue;
06847             }
06848             /* if got exception */
06849             if (fds[0].revents & POLLPRI)
06850                return -1;
06851             if (!(fds[0].revents & POLLOUT)) {
06852                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06853                continue;
06854             }
06855             res = write(fd, buf, size);
06856             if (res != size) {
06857                if (res == -1) return -1;
06858                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06859                break;
06860             }
06861             len -= size;
06862             buf += size;
06863          }
06864          p->didtdd = 1; /* set to have done it now */
06865       }
06866       if (*cp == 2) { /* Mate mode */
06867          if (p->tdd)
06868             tdd_free(p->tdd);
06869          p->tdd = 0;
06870          p->mate = 1;
06871          break;
06872       }
06873       if (!p->tdd) { /* if we don't have one yet */
06874          p->tdd = tdd_new(); /* allocate one */
06875       }
06876       break;
06877    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06878       if (!p->dsp)
06879          break;
06880       cp = (char *) data;
06881       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06882          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06883       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06884       break;
06885    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06886 #if defined(HAVE_PRI)
06887       if (dahdi_sig_pri_lib_handles(p->sig)
06888          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06889          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06890          break;
06891       }
06892 #endif   /* defined(HAVE_PRI) */
06893 
06894       cp = (char *) data;
06895       if (!*cp) {
06896          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06897          x = 0;
06898          dahdi_disable_ec(p);
06899       } else {
06900          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06901          x = 1;
06902       }
06903       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06904          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06905       break;
06906    case AST_OPTION_OPRMODE:  /* Operator services mode */
06907       oprmode = (struct oprmode *) data;
06908       /* We don't support operator mode across technologies */
06909       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06910          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06911                chan->tech->type, oprmode->peer->tech->type);
06912          errno = EINVAL;
06913          return -1;
06914       }
06915       pp = oprmode->peer->tech_pvt;
06916       p->oprmode = pp->oprmode = 0;
06917       /* setup peers */
06918       p->oprpeer = pp;
06919       pp->oprpeer = p;
06920       /* setup modes, if any */
06921       if (oprmode->mode)
06922       {
06923          pp->oprmode = oprmode->mode;
06924          p->oprmode = -oprmode->mode;
06925       }
06926       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06927          oprmode->mode, chan->name,oprmode->peer->name);
06928       break;
06929    case AST_OPTION_ECHOCAN:
06930       cp = (char *) data;
06931       if (*cp) {
06932          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06933          dahdi_enable_ec(p);
06934       } else {
06935          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06936          dahdi_disable_ec(p);
06937       }
06938       break;
06939    case AST_OPTION_DIGIT_DETECT:
06940       cp = (char *) data;
06941       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06942       if (*cp) {
06943          enable_dtmf_detect(p);
06944       } else {
06945          disable_dtmf_detect(p);
06946       }
06947       break;
06948    case AST_OPTION_FAX_DETECT:
06949       cp = (char *) data;
06950       if (p->dsp) {
06951          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06952          if (*cp) {
06953             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06954          } else {
06955             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06956          }
06957          ast_dsp_set_features(p->dsp, p->dsp_features);
06958       }
06959       break;
06960    default:
06961       return -1;
06962    }
06963    errno = 0;
06964 
06965    return 0;
06966 }

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

Definition at line 15476 of file chan_dahdi.c.

References sig_pri_chan::allocated, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, sig_pri_chan::call, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::channel, sig_ss7_chan::cic, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_ton, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_pvt::confno, dahdi_pvt::context, dahdi_dnd(), dahdi_pvt::destroy, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, ast_cli_args::fd, dahdi_pvt::head, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, ISTRUNK, dahdi_pvt::law_default, dahdi_subchannel::linear, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::master, MAX_SLAVES, ast_variable::name, ast_variable::next, dahdi_pvt::next, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::params, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::radio, sig_pri_chan::resetting, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, S_OR, dahdi_pvt::sig, sig2str, SIG_PRI_RESET_IDLE, dahdi_pvt::sig_pvt, 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.

15477 {
15478    int channel;
15479    struct dahdi_pvt *tmp = NULL;
15480    struct dahdi_confinfo ci;
15481    struct dahdi_params ps;
15482    int x;
15483 
15484    switch (cmd) {
15485    case CLI_INIT:
15486       e->command = "dahdi show channel";
15487       e->usage =
15488          "Usage: dahdi show channel <chan num>\n"
15489          "  Detailed information about a given channel\n";
15490       return NULL;
15491    case CLI_GENERATE:
15492       return NULL;
15493    }
15494 
15495    if (a->argc != 4)
15496       return CLI_SHOWUSAGE;
15497 
15498    channel = atoi(a->argv[3]);
15499 
15500    ast_mutex_lock(&iflock);
15501    for (tmp = iflist; tmp; tmp = tmp->next) {
15502       if (tmp->channel == channel) {
15503          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15504          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15505          ast_cli(a->fd, "Span: %d\n", tmp->span);
15506          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15507          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15508          ast_cli(a->fd, "Context: %s\n", tmp->context);
15509          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15510          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15511 #if defined(HAVE_PRI)
15512 #if defined(HAVE_PRI_SUBADDR)
15513          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15514 #endif   /* defined(HAVE_PRI_SUBADDR) */
15515 #endif   /* defined(HAVE_PRI) */
15516          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15517          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15518          if (tmp->vars) {
15519             struct ast_variable *v;
15520             ast_cli(a->fd, "Variables:\n");
15521             for (v = tmp->vars ; v ; v = v->next)
15522                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15523          }
15524          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15525          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15526          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15527          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15528          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15529          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)" : "");
15530          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)" : "");
15531          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)" : "");
15532          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15533          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15534          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15535          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15536          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15537          if (tmp->busydetect) {
15538 #if defined(BUSYDETECT_TONEONLY)
15539             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15540 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15541             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15542 #endif
15543 #ifdef BUSYDETECT_DEBUG
15544             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15545 #endif
15546             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15547             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
15548          }
15549          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15550          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15551          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15552          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15553          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15554          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15555          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15556          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15557          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15558          ast_cli(a->fd, "Echo Cancellation:\n");
15559 
15560          if (tmp->echocancel.head.tap_length) {
15561             ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length);
15562             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15563                ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15564             }
15565             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15566          } else {
15567             ast_cli(a->fd, "\tnone\n");
15568          }
15569          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15570          if (tmp->master)
15571             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15572          for (x = 0; x < MAX_SLAVES; x++) {
15573             if (tmp->slaves[x])
15574                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15575          }
15576 #ifdef HAVE_OPENR2
15577          if (tmp->mfcr2) {
15578             char calldir[OR2_MAX_PATH];
15579             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15580             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15581             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15582             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15583             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15584             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15585             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15586             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15587             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15588             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15589             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15590 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15591             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15592 #endif
15593             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15594             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15595             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15596             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15597             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15598             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15599             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15600             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15601             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15602             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15603             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15604             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15605          }
15606 #endif
15607 #if defined(HAVE_SS7)
15608          if (tmp->ss7) {
15609             struct sig_ss7_chan *chan = tmp->sig_pvt;
15610 
15611             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15612          }
15613 #endif   /* defined(HAVE_SS7) */
15614 #ifdef HAVE_PRI
15615          if (tmp->pri) {
15616             struct sig_pri_chan *chan = tmp->sig_pvt;
15617 
15618             ast_cli(a->fd, "PRI Flags: ");
15619             if (chan->resetting != SIG_PRI_RESET_IDLE) {
15620                ast_cli(a->fd, "Resetting=%u ", chan->resetting);
15621             }
15622             if (chan->call)
15623                ast_cli(a->fd, "Call ");
15624             if (chan->allocated) {
15625                ast_cli(a->fd, "Allocated ");
15626             }
15627             ast_cli(a->fd, "\n");
15628             if (tmp->logicalspan)
15629                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15630             else
15631                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15632          }
15633 #endif
15634          memset(&ci, 0, sizeof(ci));
15635          ps.channo = tmp->channel;
15636          if (tmp->subs[SUB_REAL].dfd > -1) {
15637             memset(&ci, 0, sizeof(ci));
15638             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15639                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode);
15640             }
15641             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15642                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15643             }
15644             memset(&ps, 0, sizeof(ps));
15645             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15646                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15647             } else {
15648                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15649             }
15650          }
15651          if (ISTRUNK(tmp)) {
15652             ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
15653             if (!ast_strlen_zero(progzone))
15654                ast_cli(a->fd, "Progress Zone: %s\n", progzone);
15655             ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
15656             if(tmp->busydetect) {
15657                ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
15658                if(tmp->busytonelength > 0) {
15659                   ast_cli(a->fd, "Busy Pattern:\n");
15660                   ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
15661                   if (tmp->busyquietlength > 0) 
15662                      ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
15663                   else 
15664                      ast_cli(a->fd, " -- Detect Tone Only\n");
15665                   if(tmp->busyfuzziness > 0)
15666                      ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
15667                }
15668             }
15669          }
15670          ast_mutex_unlock(&iflock);
15671          return CLI_SUCCESS;
15672       }
15673    }
15674    ast_mutex_unlock(&iflock);
15675 
15676    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15677    return CLI_FAILURE;
15678 }

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

Definition at line 15389 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_pvt::context, dahdi_pvt::exten, ast_cli_args::fd, FORMAT, FORMAT2, dahdi_pvt::group, dahdi_pvt::language, dahdi_pvt::locallyblocked, dahdi_pvt::mohinterpret, dahdi_pvt::next, dahdi_pvt::remotelyblocked, and ast_cli_entry::usage.

15390 {
15391 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15392 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15393    ast_group_t targetnum = 0;
15394    int filtertype = 0;
15395    struct dahdi_pvt *tmp = NULL;
15396    char tmps[20] = "";
15397    char statestr[20] = "";
15398    char blockstr[20] = "";
15399 
15400    switch (cmd) {
15401    case CLI_INIT:
15402       e->command = "dahdi show channels [group|context]";
15403       e->usage =
15404          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15405          "  Shows a list of available channels with optional filtering\n"
15406          "  <group> must be a number between 0 and 63\n";
15407       return NULL;
15408    case CLI_GENERATE:
15409       return NULL;
15410    }
15411 
15412    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15413 
15414    if (!((a->argc == 3) || (a->argc == 5)))
15415       return CLI_SHOWUSAGE;
15416 
15417    if (a->argc == 5) {
15418       if (!strcasecmp(a->argv[3], "group")) {
15419          targetnum = atoi(a->argv[4]);
15420          if (63 < targetnum) {
15421             return CLI_SHOWUSAGE;
15422          }
15423          targetnum = ((ast_group_t) 1) << targetnum;
15424          filtertype = 1;
15425       } else if (!strcasecmp(a->argv[3], "context")) {
15426          filtertype = 2;
15427       }
15428    }
15429 
15430    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15431    ast_mutex_lock(&iflock);
15432    for (tmp = iflist; tmp; tmp = tmp->next) {
15433       if (filtertype) {
15434          switch(filtertype) {
15435          case 1: /* dahdi show channels group <group> */
15436             if (!(tmp->group & targetnum)) {
15437                continue;
15438             }
15439             break;
15440          case 2: /* dahdi show channels context <context> */
15441             if (strcasecmp(tmp->context, a->argv[4])) {
15442                continue;
15443             }
15444             break;
15445          default:
15446             break;
15447          }
15448       }
15449       if (tmp->channel > 0) {
15450          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15451       } else
15452          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15453 
15454       if (tmp->locallyblocked)
15455          blockstr[0] = 'L';
15456       else
15457          blockstr[0] = ' ';
15458 
15459       if (tmp->remotelyblocked)
15460          blockstr[1] = 'R';
15461       else
15462          blockstr[1] = ' ';
15463 
15464       blockstr[2] = '\0';
15465 
15466       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15467 
15468       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15469    }
15470    ast_mutex_unlock(&iflock);
15471    return CLI_SUCCESS;
15472 #undef FORMAT
15473 #undef FORMAT2
15474 }

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

Definition at line 15717 of file chan_dahdi.c.

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

15718 {
15719    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15720    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15721    int span;
15722    int res;
15723    char alarmstr[50];
15724 
15725    int ctl;
15726    struct dahdi_spaninfo s;
15727 
15728    switch (cmd) {
15729    case CLI_INIT:
15730       e->command = "dahdi show status";
15731       e->usage =
15732          "Usage: dahdi show status\n"
15733          "       Shows a list of DAHDI cards with status\n";
15734       return NULL;
15735    case CLI_GENERATE:
15736       return NULL;
15737    }
15738    ctl = open("/dev/dahdi/ctl", O_RDWR);
15739    if (ctl < 0) {
15740       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15741       return CLI_FAILURE;
15742    }
15743    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15744 
15745    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15746       s.spanno = span;
15747       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15748       if (res) {
15749          continue;
15750       }
15751       alarmstr[0] = '\0';
15752       if (s.alarms > 0) {
15753          if (s.alarms & DAHDI_ALARM_BLUE)
15754             strcat(alarmstr, "BLU/");
15755          if (s.alarms & DAHDI_ALARM_YELLOW)
15756             strcat(alarmstr, "YEL/");
15757          if (s.alarms & DAHDI_ALARM_RED)
15758             strcat(alarmstr, "RED/");
15759          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15760             strcat(alarmstr, "LB/");
15761          if (s.alarms & DAHDI_ALARM_RECOVER)
15762             strcat(alarmstr, "REC/");
15763          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15764             strcat(alarmstr, "NOP/");
15765          if (!strlen(alarmstr))
15766             strcat(alarmstr, "UUU/");
15767          if (strlen(alarmstr)) {
15768             /* Strip trailing / */
15769             alarmstr[strlen(alarmstr) - 1] = '\0';
15770          }
15771       } else {
15772          if (s.numchans)
15773             strcpy(alarmstr, "OK");
15774          else
15775             strcpy(alarmstr, "UNCONFIGURED");
15776       }
15777 
15778       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15779          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15780          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15781          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15782          "CAS",
15783          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15784          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15785          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15786          "Unk",
15787          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15788             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15789             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15790          lbostr[s.lbo]
15791          );
15792    }
15793    close(ctl);
15794 
15795    return CLI_SUCCESS;
15796 #undef FORMAT
15797 #undef FORMAT2
15798 }

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

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

15801 {
15802    int pseudo_fd = -1;
15803    struct dahdi_versioninfo vi;
15804 
15805    switch (cmd) {
15806    case CLI_INIT:
15807       e->command = "dahdi show version";
15808       e->usage =
15809          "Usage: dahdi show version\n"
15810          "       Shows the DAHDI version in use\n";
15811       return NULL;
15812    case CLI_GENERATE:
15813       return NULL;
15814    }
15815    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15816       ast_cli(a->fd, "Failed to open control file to get version.\n");
15817       return CLI_SUCCESS;
15818    }
15819 
15820    strcpy(vi.version, "Unknown");
15821    strcpy(vi.echo_canceller, "Unknown");
15822 
15823    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15824       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15825    else
15826       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15827 
15828    close(pseudo_fd);
15829 
15830    return CLI_SUCCESS;
15831 }

static char* dahdi_sig2str ( int  sig  )  [static]

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

Referenced by mkintf().

04669 {
04670    static char buf[256];
04671    switch (sig) {
04672    case SIG_EM:
04673       return "E & M Immediate";
04674    case SIG_EMWINK:
04675       return "E & M Wink";
04676    case SIG_EM_E1:
04677       return "E & M E1";
04678    case SIG_FEATD:
04679       return "Feature Group D (DTMF)";
04680    case SIG_FEATDMF:
04681       return "Feature Group D (MF)";
04682    case SIG_FEATDMF_TA:
04683       return "Feature Groud D (MF) Tandem Access";
04684    case SIG_FEATB:
04685       return "Feature Group B (MF)";
04686    case SIG_E911:
04687       return "E911 (MF)";
04688    case SIG_FGC_CAMA:
04689       return "FGC/CAMA (Dialpulse)";
04690    case SIG_FGC_CAMAMF:
04691       return "FGC/CAMA (MF)";
04692    case SIG_FXSLS:
04693       return "FXS Loopstart";
04694    case SIG_FXSGS:
04695       return "FXS Groundstart";
04696    case SIG_FXSKS:
04697       return "FXS Kewlstart";
04698    case SIG_FXOLS:
04699       return "FXO Loopstart";
04700    case SIG_FXOGS:
04701       return "FXO Groundstart";
04702    case SIG_FXOKS:
04703       return "FXO Kewlstart";
04704    case SIG_PRI:
04705       return "ISDN PRI";
04706    case SIG_BRI:
04707       return "ISDN BRI Point to Point";
04708    case SIG_BRI_PTMP:
04709       return "ISDN BRI Point to MultiPoint";
04710    case SIG_SS7:
04711       return "SS7";
04712    case SIG_MFCR2:
04713       return "MFC/R2";
04714    case SIG_SF:
04715       return "SF (Tone) Immediate";
04716    case SIG_SFWINK:
04717       return "SF (Tone) Wink";
04718    case SIG_SF_FEATD:
04719       return "SF (Tone) with Feature Group D (DTMF)";
04720    case SIG_SF_FEATDMF:
04721       return "SF (Tone) with Feature Group D (MF)";
04722    case SIG_SF_FEATB:
04723       return "SF (Tone) with Feature Group B (MF)";
04724    case 0:
04725       return "Pseudo";
04726    default:
04727       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04728       return buf;
04729    }
04730 }

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

Definition at line 1562 of file chan_dahdi.c.

References SIG_PRI_LIB_HANDLE_CASES.

Referenced by dahdi_bridge(), dahdi_call(), dahdi_cc_callback(), dahdi_digit_end(), dahdi_fixup(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_queryoption(), dahdi_read(), dahdi_request(), dahdi_setoption(), handle_alarms(), handle_clear_alarms(), and mkintf().

01563 {
01564    int handles;
01565 
01566    switch (signaling) {
01567    case SIG_PRI_LIB_HANDLE_CASES:
01568       handles = 1;
01569       break;
01570    default:
01571       handles = 0;
01572       break;
01573    }
01574 
01575    return handles;
01576 }

static void dahdi_softhangup_all ( void   )  [static]

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

Referenced by dahdi_restart().

15216 {
15217    struct dahdi_pvt *p;
15218 retry:
15219    ast_mutex_lock(&iflock);
15220    for (p = iflist; p; p = p->next) {
15221       ast_mutex_lock(&p->lock);
15222       if (p->owner && !p->restartpending) {
15223          if (ast_channel_trylock(p->owner)) {
15224             if (option_debug > 2)
15225                ast_verbose("Avoiding deadlock\n");
15226             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15227             ast_mutex_unlock(&p->lock);
15228             ast_mutex_unlock(&iflock);
15229             goto retry;
15230          }
15231          if (option_debug > 2)
15232             ast_verbose("Softhanging up on %s\n", p->owner->name);
15233          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15234          p->restartpending = 1;
15235          num_restart_pending++;
15236          ast_channel_unlock(p->owner);
15237       }
15238       ast_mutex_unlock(&p->lock);
15239    }
15240    ast_mutex_unlock(&iflock);
15241 }

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

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

18608 {
18609    int ctl, res, span;
18610    struct ast_data *data_span, *data_alarms;
18611    struct dahdi_spaninfo s;
18612 
18613    ctl = open("/dev/dahdi/ctl", O_RDWR);
18614    if (ctl < 0) {
18615       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18616       return -1;
18617    }
18618    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18619       s.spanno = span;
18620       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18621       if (res) {
18622          continue;
18623       }
18624 
18625       data_span = ast_data_add_node(data_root, "span");
18626       if (!data_span) {
18627          continue;
18628       }
18629       ast_data_add_str(data_span, "description", s.desc);
18630 
18631       /* insert the alarms status */
18632       data_alarms = ast_data_add_node(data_span, "alarms");
18633       if (!data_alarms) {
18634          continue;
18635       }
18636 
18637       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18638       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18639       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18640       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18641       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18642       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18643 
18644       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18645       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18646       ast_data_add_int(data_span, "crc4", s.crc4count);
18647       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18648                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18649                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18650                      "CAS");
18651       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18652                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18653                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18654                      "Unknown");
18655       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18656                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18657                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18658       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18659 
18660       /* if this span doesn't match remove it. */
18661       if (!ast_data_search_match(search, data_span)) {
18662          ast_data_remove_node(data_root, data_span);
18663       }
18664    }
18665    close(ctl);
18666 
18667    return 0;
18668 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

Definition at line 4971 of file chan_dahdi.c.

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

Referenced by dahdi_handle_event(), and my_train_echocanceller().

04972 {
04973    int x;
04974    int res;
04975 
04976    if (p && p->echocanon && p->echotraining) {
04977       x = p->echotraining;
04978       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04979       if (res)
04980          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04981       else
04982          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04983    } else {
04984       ast_debug(1, "No echo training requested\n");
04985    }
04986 }

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

Definition at line 7181 of file chan_dahdi.c.

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

Referenced by dahdi_bridge(), and dahdi_fixup().

07182 {
07183    /* Unlink a specific slave or all slaves/masters from a given master */
07184    int x;
07185    int hasslaves;
07186    if (!master)
07187       return;
07188    if (needlock) {
07189       ast_mutex_lock(&master->lock);
07190       if (slave) {
07191          while (ast_mutex_trylock(&slave->lock)) {
07192             DEADLOCK_AVOIDANCE(&master->lock);
07193          }
07194       }
07195    }
07196    hasslaves = 0;
07197    for (x = 0; x < MAX_SLAVES; x++) {
07198       if (master->slaves[x]) {
07199          if (!slave || (master->slaves[x] == slave)) {
07200             /* Take slave out of the conference */
07201             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07202             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07203             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07204             master->slaves[x]->master = NULL;
07205             master->slaves[x] = NULL;
07206          } else
07207             hasslaves = 1;
07208       }
07209       if (!hasslaves)
07210          master->inconference = 0;
07211    }
07212    if (!slave) {
07213       if (master->master) {
07214          /* Take master out of the conference */
07215          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07216          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07217          hasslaves = 0;
07218          for (x = 0; x < MAX_SLAVES; x++) {
07219             if (master->master->slaves[x] == master)
07220                master->master->slaves[x] = NULL;
07221             else if (master->master->slaves[x])
07222                hasslaves = 1;
07223          }
07224          if (!hasslaves)
07225             master->master->inconference = 0;
07226       }
07227       master->master = NULL;
07228    }
07229    update_conf(master);
07230    if (needlock) {
07231       if (slave)
07232          ast_mutex_unlock(&slave->lock);
07233       ast_mutex_unlock(&master->lock);
07234    }
07235 }

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

Definition at line 18709 of file chan_dahdi.c.

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

18711 {
18712    int pseudo_fd = -1;
18713    struct dahdi_versioninfo vi = {
18714       .version = "Unknown",
18715       .echo_canceller = "Unknown"
18716    };
18717 
18718    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18719       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18720       return -1;
18721    }
18722 
18723    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18724       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18725    }
18726 
18727    close(pseudo_fd);
18728 
18729    ast_data_add_str(data_root, "value", vi.version);
18730    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18731 
18732    return 0;
18733 }

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Referenced by analog_ss_thread(), and my_wait_event().

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

Definition at line 9893 of file chan_dahdi.c.

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

Referenced by analog_ss_thread(), and my_wink().

09894 {
09895    int j;
09896    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09897    for (;;)
09898    {
09899       /* set bits of interest */
09900       j = DAHDI_IOMUX_SIGEVENT;
09901       /* wait for some happening */
09902       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09903       /* exit loop if we have it */
09904       if (j & DAHDI_IOMUX_SIGEVENT) break;
09905    }
09906    /* get the event info */
09907    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09908    return 0;
09909 }

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

Definition at line 9414 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, LOG_WARNING, my_dahdi_write(), dahdi_pvt::owner, ast_frame::ptr, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.

09415 {
09416    struct dahdi_pvt *p = ast->tech_pvt;
09417    int res;
09418    int idx;
09419    idx = dahdi_get_index(ast, p, 0);
09420    if (idx < 0) {
09421       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09422       return -1;
09423    }
09424 
09425    /* Write a frame of (presumably voice) data */
09426    if (frame->frametype != AST_FRAME_VOICE) {
09427       if (frame->frametype != AST_FRAME_IMAGE)
09428          ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype);
09429       return 0;
09430    }
09431    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09432       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09433       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09434       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09435       return -1;
09436    }
09437    if (p->dialing) {
09438       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09439       return 0;
09440    }
09441    if (!p->owner) {
09442       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09443       return 0;
09444    }
09445    if (p->cidspill) {
09446       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09447          ast->name);
09448       return 0;
09449    }
09450    /* Return if it's not valid data */
09451    if (!frame->data.ptr || !frame->datalen)
09452       return 0;
09453 
09454    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09455       if (!p->subs[idx].linear) {
09456          p->subs[idx].linear = 1;
09457          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09458          if (res)
09459             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09460       }
09461       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09462    } else {
09463       /* x-law already */
09464       if (p->subs[idx].linear) {
09465          p->subs[idx].linear = 0;
09466          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09467          if (res)
09468             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09469       }
09470       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09471    }
09472    if (res < 0) {
09473       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09474       return -1;
09475    }
09476    return 0;
09477 }

static enum analog_event dahdievent_to_analogevent ( int  event  )  [static]

Definition at line 2796 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 do_monitor(), my_get_callerid(), and my_get_event().

02797 {
02798    enum analog_event res;
02799 
02800    switch (event) {
02801    case DAHDI_EVENT_ONHOOK:
02802       res = ANALOG_EVENT_ONHOOK;
02803       break;
02804    case DAHDI_EVENT_RINGOFFHOOK:
02805       res = ANALOG_EVENT_RINGOFFHOOK;
02806       break;
02807    case DAHDI_EVENT_WINKFLASH:
02808       res = ANALOG_EVENT_WINKFLASH;
02809       break;
02810    case DAHDI_EVENT_ALARM:
02811       res = ANALOG_EVENT_ALARM;
02812       break;
02813    case DAHDI_EVENT_NOALARM:
02814       res = ANALOG_EVENT_NOALARM;
02815       break;
02816    case DAHDI_EVENT_DIALCOMPLETE:
02817       res = ANALOG_EVENT_DIALCOMPLETE;
02818       break;
02819    case DAHDI_EVENT_RINGERON:
02820       res = ANALOG_EVENT_RINGERON;
02821       break;
02822    case DAHDI_EVENT_RINGEROFF:
02823       res = ANALOG_EVENT_RINGEROFF;
02824       break;
02825    case DAHDI_EVENT_HOOKCOMPLETE:
02826       res = ANALOG_EVENT_HOOKCOMPLETE;
02827       break;
02828    case DAHDI_EVENT_PULSE_START:
02829       res = ANALOG_EVENT_PULSE_START;
02830       break;
02831    case DAHDI_EVENT_POLARITY:
02832       res = ANALOG_EVENT_POLARITY;
02833       break;
02834    case DAHDI_EVENT_RINGBEGIN:
02835       res = ANALOG_EVENT_RINGBEGIN;
02836       break;
02837    case DAHDI_EVENT_EC_DISABLED:
02838       res = ANALOG_EVENT_EC_DISABLED;
02839       break;
02840    case DAHDI_EVENT_REMOVED:
02841       res = ANALOG_EVENT_REMOVED;
02842       break;
02843    case DAHDI_EVENT_NEONMWI_ACTIVE:
02844       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02845       break;
02846    case DAHDI_EVENT_NEONMWI_INACTIVE:
02847       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02848       break;
02849 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02850    case DAHDI_EVENT_TX_CED_DETECTED:
02851       res = ANALOG_EVENT_TX_CED_DETECTED;
02852       break;
02853    case DAHDI_EVENT_RX_CED_DETECTED:
02854       res = ANALOG_EVENT_RX_CED_DETECTED;
02855       break;
02856    case DAHDI_EVENT_EC_NLP_DISABLED:
02857       res = ANALOG_EVENT_EC_NLP_DISABLED;
02858       break;
02859    case DAHDI_EVENT_EC_NLP_ENABLED:
02860       res = ANALOG_EVENT_EC_NLP_ENABLED;
02861       break;
02862 #endif
02863    case DAHDI_EVENT_PULSEDIGIT:
02864       res = ANALOG_EVENT_PULSEDIGIT;
02865       break;
02866    case DAHDI_EVENT_DTMFDOWN:
02867       res = ANALOG_EVENT_DTMFDOWN;
02868       break;
02869    case DAHDI_EVENT_DTMFUP:
02870       res = ANALOG_EVENT_DTMFUP;
02871       break;
02872    default:
02873       switch(event & 0xFFFF0000) {
02874       case DAHDI_EVENT_PULSEDIGIT:
02875       case DAHDI_EVENT_DTMFDOWN:
02876       case DAHDI_EVENT_DTMFUP:
02877          /* The event includes a digit number in the low word.
02878           * Converting it to a 'enum analog_event' would remove
02879           * that information. Thus it is returned as-is.
02880           */
02881          return event;
02882       }
02883 
02884       res = ANALOG_EVENT_ERROR;
02885       break;
02886    }
02887 
02888    return res;
02889 }

static enum analog_sigtype dahdisig_to_analogsig ( int  sig  )  [static]

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

Referenced by mkintf().

01620 {
01621    switch (sig) {
01622    case SIG_FXOLS:
01623       return ANALOG_SIG_FXOLS;
01624    case SIG_FXOGS:
01625       return ANALOG_SIG_FXOGS;
01626    case SIG_FXOKS:
01627       return ANALOG_SIG_FXOKS;
01628    case SIG_FXSLS:
01629       return ANALOG_SIG_FXSLS;
01630    case SIG_FXSGS:
01631       return ANALOG_SIG_FXSGS;
01632    case SIG_FXSKS:
01633       return ANALOG_SIG_FXSKS;
01634    case SIG_EMWINK:
01635       return ANALOG_SIG_EMWINK;
01636    case SIG_EM:
01637       return ANALOG_SIG_EM;
01638    case SIG_EM_E1:
01639       return ANALOG_SIG_EM_E1;
01640    case SIG_FEATD:
01641       return ANALOG_SIG_FEATD;
01642    case SIG_FEATDMF:
01643       return ANALOG_SIG_FEATDMF;
01644    case SIG_E911:
01645       return SIG_E911;
01646    case SIG_FGC_CAMA:
01647       return ANALOG_SIG_FGC_CAMA;
01648    case SIG_FGC_CAMAMF:
01649       return ANALOG_SIG_FGC_CAMAMF;
01650    case SIG_FEATB:
01651       return ANALOG_SIG_FEATB;
01652    case SIG_SFWINK:
01653       return ANALOG_SIG_SFWINK;
01654    case SIG_SF:
01655       return ANALOG_SIG_SF;
01656    case SIG_SF_FEATD:
01657       return ANALOG_SIG_SF_FEATD;
01658    case SIG_SF_FEATDMF:
01659       return ANALOG_SIG_SF_FEATDMF;
01660    case SIG_FEATDMF_TA:
01661       return ANALOG_SIG_FEATDMF_TA;
01662    case SIG_SF_FEATB:
01663       return ANALOG_SIG_FEATB;
01664    default:
01665       return -1;
01666    }
01667 }

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

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

18272 {
18273    struct ast_cc_config_params *cc_params;
18274 
18275    cc_params = dest->chan.cc_params;
18276    *dest = *src;
18277    dest->chan.cc_params = cc_params;
18278    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18279 }

static void destroy_all_channels ( void   )  [static]

Definition at line 5866 of file chan_dahdi.c.

References ast_db_del(), ast_db_get(), ast_mutex_lock, ast_mutex_unlock, ast_verb, dahdi_pvt::channel, destroy_dahdi_pvt(), sig_pri_span::lock, sig_pri_span::no_b_chan_iflist, NUM_SPANS, sig_pri_span::pri, and dahdi_pvt::span.

Referenced by __unload_module(), and dahdi_restart().

05867 {
05868    int chan;
05869 #if defined(HAVE_PRI)
05870    unsigned span;
05871    struct sig_pri_span *pri;
05872 #endif   /* defined(HAVE_PRI) */
05873    struct dahdi_pvt *p;
05874 
05875    while (num_restart_pending) {
05876       usleep(1);
05877    }
05878 
05879    ast_mutex_lock(&iflock);
05880    /* Destroy all the interfaces and free their memory */
05881    while (iflist) {
05882       p = iflist;
05883 
05884       chan = p->channel;
05885 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05886       {
05887          char db_chan_name[20];
05888          char db_answer[5];
05889          char state;
05890          int why = -1;
05891 
05892          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05893          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05894             sscanf(db_answer, "%1c:%30d", &state, &why);
05895          }
05896          if (!why) {
05897             /* SRVST persistence is not required */
05898             ast_db_del(db_chan_name, SRVST_DBKEY);
05899          }
05900       }
05901 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05902       /* Free associated memory */
05903       destroy_dahdi_pvt(p);
05904       ast_verb(3, "Unregistered channel %d\n", chan);
05905    }
05906    ifcount = 0;
05907    ast_mutex_unlock(&iflock);
05908 
05909 #if defined(HAVE_PRI)
05910    /* Destroy all of the no B channel interface lists */
05911    for (span = 0; span < NUM_SPANS; ++span) {
05912       if (!pris[span].dchannels[0]) {
05913          break;
05914       }
05915       pri = &pris[span].pri;
05916       ast_mutex_lock(&pri->lock);
05917       while (pri->no_b_chan_iflist) {
05918          p = pri->no_b_chan_iflist;
05919 
05920          /* Free associated memory */
05921          destroy_dahdi_pvt(p);
05922       }
05923       ast_mutex_unlock(&pri->lock);
05924    }
05925 #endif   /* defined(HAVE_PRI) */
05926 }

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

Definition at line 5848 of file chan_dahdi.c.

References destroy_dahdi_pvt(), dahdi_subchannel::owner, dahdi_pvt::owner, and dahdi_pvt::subs.

Referenced by dahdi_destroy_channel_bynum(), and dahdi_hangup().

05849 {
05850    int i;
05851 
05852    if (!now) {
05853       /* Do not destroy the channel now if it is owned by someone. */
05854       if (cur->owner) {
05855          return;
05856       }
05857       for (i = 0; i < 3; i++) {
05858          if (cur->subs[i].owner) {
05859             return;
05860          }
05861       }
05862    }
05863    destroy_dahdi_pvt(cur);
05864 }

static void destroy_dahdi_pvt ( struct dahdi_pvt pvt  )  [static]

Definition at line 5778 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_NONE, 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::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(), destroy_channel(), duplicate_pseudo(), and mkintf().

05779 {
05780    struct dahdi_pvt *p = pvt;
05781 
05782    if (p->manages_span_alarms) {
05783       struct dahdi_pvt *next = find_next_iface_in_span(p);
05784       if (next) {
05785          next->manages_span_alarms = 1;
05786       }
05787    }
05788 
05789    /* Remove channel from the list */
05790 #if defined(HAVE_PRI)
05791    dahdi_unlink_pri_pvt(p);
05792 #endif   /* defined(HAVE_PRI) */
05793 #if defined(HAVE_SS7)
05794    dahdi_unlink_ss7_pvt(p);
05795 #endif   /* defined(HAVE_SS7) */
05796    switch (pvt->which_iflist) {
05797    case DAHDI_IFLIST_NONE:
05798       break;
05799    case DAHDI_IFLIST_MAIN:
05800       dahdi_iflist_extract(p);
05801       break;
05802 #if defined(HAVE_PRI)
05803    case DAHDI_IFLIST_NO_B_CHAN:
05804       if (p->pri) {
05805          dahdi_nobch_extract(p->pri, p);
05806       }
05807       break;
05808 #endif   /* defined(HAVE_PRI) */
05809    }
05810 
05811    if (p->sig_pvt) {
05812       if (analog_lib_handles(p->sig, 0, 0)) {
05813          analog_delete(p->sig_pvt);
05814       }
05815       switch (p->sig) {
05816 #if defined(HAVE_PRI)
05817       case SIG_PRI_LIB_HANDLE_CASES:
05818          sig_pri_chan_delete(p->sig_pvt);
05819          break;
05820 #endif   /* defined(HAVE_PRI) */
05821 #if defined(HAVE_SS7)
05822       case SIG_SS7:
05823          sig_ss7_chan_delete(p->sig_pvt);
05824          break;
05825 #endif   /* defined(HAVE_SS7) */
05826       default:
05827          break;
05828       }
05829    }
05830    ast_free(p->cidspill);
05831    if (p->use_smdi)
05832       ast_smdi_interface_unref(p->smdi_iface);
05833    if (p->mwi_event_sub)
05834       ast_event_unsubscribe(p->mwi_event_sub);
05835    if (p->vars) {
05836       ast_variables_destroy(p->vars);
05837    }
05838    if (p->cc_params) {
05839       ast_cc_config_params_destroy(p->cc_params);
05840    }
05841    ast_mutex_destroy(&p->lock);
05842    dahdi_close_sub(p, SUB_REAL);
05843    if (p->owner)
05844       p->owner->tech_pvt = NULL;
05845    ast_free(p);
05846 }

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

Definition at line 13560 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(), dahdi_starting_point::backwards, dahdi_starting_point::cadance, CHAN_PSEUDO, dahdi_starting_point::channelmatch, errno, dahdi_starting_point::groupmatch, LOG_ERROR, LOG_WARNING, dahdi_pvt::next, dahdi_starting_point::opt, dahdi_pvt::prev, dahdi_starting_point::roundrobin, dahdi_starting_point::rr_starting_point, and dahdi_starting_point::span.

Referenced by dahdi_cc_callback(), and dahdi_request().

13561 {
13562    char *dest;
13563    char *s;
13564    int x;
13565    int res = 0;
13566    struct dahdi_pvt *p;
13567    char *subdir = NULL;
13568    AST_DECLARE_APP_ARGS(args,
13569       AST_APP_ARG(group);  /* channel/group token */
13570       //AST_APP_ARG(ext);  /* extension token */
13571       //AST_APP_ARG(opts); /* options token */
13572       AST_APP_ARG(other);  /* Any remining unused arguments */
13573    );
13574 
13575    /*
13576     * data is ---v
13577     * Dial(DAHDI/pseudo[/extension[/options]])
13578     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13579     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13580     * Dial(DAHDI/i<span>[/extension[/options]])
13581     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13582     *
13583     * i - ISDN span channel restriction.
13584     *     Used by CC to ensure that the CC recall goes out the same span.
13585     *     Also to make ISDN channel names dialable when the sequence number
13586     *     is stripped off.  (Used by DTMF attended transfer feature.)
13587     *
13588     * g - channel group allocation search forward
13589     * G - channel group allocation search backward
13590     * r - channel group allocation round robin search forward
13591     * R - channel group allocation round robin search backward
13592     *
13593     * c - Wait for DTMF digit to confirm answer
13594     * r<cadance#> - Set distintive ring cadance number
13595     * d - Force bearer capability for ISDN/SS7 call to digital.
13596     */
13597 
13598    if (data) {
13599       dest = ast_strdupa(data);
13600    } else {
13601       ast_log(LOG_WARNING, "Channel requested with no data\n");
13602       return NULL;
13603    }
13604    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13605    if (!args.argc || ast_strlen_zero(args.group)) {
13606       ast_log(LOG_WARNING, "No channel/group specified\n");
13607       return NULL;
13608    }
13609 
13610    /* Initialize the output parameters */
13611    memset(param, 0, sizeof(*param));
13612    param->channelmatch = -1;
13613 
13614    if (strchr(args.group, '!') != NULL) {
13615       char *prev = args.group;
13616       while ((s = strchr(prev, '!')) != NULL) {
13617          *s++ = '/';
13618          prev = s;
13619       }
13620       *(prev - 1) = '\0';
13621       subdir = args.group;
13622       args.group = prev;
13623    } else if (args.group[0] == 'i') {
13624       /* Extract the ISDN span channel restriction specifier. */
13625       res = sscanf(args.group + 1, "%30d", &x);
13626       if (res < 1) {
13627          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13628          return NULL;
13629       }
13630       param->span = x;
13631 
13632       /* Remove the ISDN span channel restriction specifier. */
13633       s = strchr(args.group, '-');
13634       if (!s) {
13635          /* Search all groups since we are ISDN span restricted. */
13636          return iflist;
13637       }
13638       args.group = s + 1;
13639       res = 0;
13640    }
13641    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13642       /* Retrieve the group number */
13643       s = args.group + 1;
13644       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13645       if (res < 1) {
13646          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13647          return NULL;
13648       }
13649       param->groupmatch = ((ast_group_t) 1 << x);
13650 
13651       if (toupper(args.group[0]) == 'G') {
13652          if (args.group[0] == 'G') {
13653             param->backwards = 1;
13654             p = ifend;
13655          } else
13656             p = iflist;
13657       } else {
13658          if (ARRAY_LEN(round_robin) <= x) {
13659             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13660                x, data);
13661             return NULL;
13662          }
13663          if (args.group[0] == 'R') {
13664             param->backwards = 1;
13665             p = round_robin[x] ? round_robin[x]->prev : ifend;
13666             if (!p)
13667                p = ifend;
13668          } else {
13669             p = round_robin[x] ? round_robin[x]->next : iflist;
13670             if (!p)
13671                p = iflist;
13672          }
13673          param->roundrobin = 1;
13674          param->rr_starting_point = x;
13675       }
13676    } else {
13677       s = args.group;
13678       if (!strcasecmp(s, "pseudo")) {
13679          /* Special case for pseudo */
13680          x = CHAN_PSEUDO;
13681          param->channelmatch = x;
13682       } else {
13683          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13684          if (res < 1) {
13685             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13686             return NULL;
13687          } else {
13688             param->channelmatch = x;
13689          }
13690       }
13691       if (subdir) {
13692          char path[PATH_MAX];
13693          struct stat stbuf;
13694 
13695          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13696                subdir, param->channelmatch);
13697          if (stat(path, &stbuf) < 0) {
13698             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13699                   path, strerror(errno));
13700             return NULL;
13701          }
13702          if (!S_ISCHR(stbuf.st_mode)) {
13703             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13704                   path);
13705             return NULL;
13706          }
13707          param->channelmatch = minor(stbuf.st_rdev);
13708       }
13709 
13710       p = iflist;
13711    }
13712 
13713    if (param->opt == 'r' && res < 3) {
13714       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13715       param->opt = '\0';
13716    }
13717 
13718    return p;
13719 }

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

Definition at line 12330 of file chan_dahdi.c.

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

Referenced by build_channels().

12331 {
12332    struct stat stbuf;
12333    int      num;
12334 
12335    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12336    if (stat(path, &stbuf) < 0) {
12337       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12338       return -errno;
12339    }
12340    if (!S_ISCHR(stbuf.st_mode)) {
12341       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12342       return -EINVAL;
12343    }
12344    num = minor(stbuf.st_rdev);
12345    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12346    return num;
12347 
12348 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 4504 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

04505 {
04506    if (isdigit(digit))
04507       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04508    else if (digit >= 'A' && digit <= 'D')
04509       return DAHDI_TONE_DTMF_A + (digit - 'A');
04510    else if (digit >= 'a' && digit <= 'd')
04511       return DAHDI_TONE_DTMF_A + (digit - 'a');
04512    else if (digit == '*')
04513       return DAHDI_TONE_DTMF_s;
04514    else if (digit == '#')
04515       return DAHDI_TONE_DTMF_p;
04516    else
04517       return -1;
04518 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 6677 of file chan_dahdi.c.

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

Referenced by dahdi_bridge(), and dahdi_setoption().

06678 {
06679    int val = 0;
06680 
06681    p->ignoredtmf = 1;
06682 
06683    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06684 
06685    if (!p->hardwaredtmf && p->dsp) {
06686       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06687       ast_dsp_set_features(p->dsp, p->dsp_features);
06688    }
06689 }

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

Definition at line 11745 of file chan_dahdi.c.

References ANALOG_EVENT_DTMFCID, analog_handle_init_event(), analog_lib_handles(), analog_ss_thread(), ast_calloc, ast_debug, ast_fdisset(), ast_free, ast_hangup(), AST_LAW, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, ast_pthread_create_detached, AST_STATE_PRERING, ast_strlen_zero(), mwi_thread_data::buf, calc_energy(), dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, dahdi_pvt::cidspill, dahdi_destroy_channel_bynum(), dahdi_get_event(), dahdi_new(), dahdievent_to_analogevent(), dahdi_subchannel::dfd, dahdi_pvt::dtmfcid_delay, dahdi_pvt::dtmfcid_holdoff_state, errno, event2str(), analog_pvt::fxsoffhookstate, handle_init_event(), has_voicemail(), last, mwi_thread_data::len, dahdi_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, dahdi_pvt::mailbox, monitor_pfds_clean(), analog_pvt::msgstate, mwi_send_init(), mwi_send_process_buffer(), mwi_send_process_event(), mwi_thread(), dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitoractive, dahdi_pvt::mwisendactive, dahdi_pvt::next, analog_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, analog_subchannel::owner, analog_pvt::owner, mwi_thread_data::pvt, dahdi_pvt::radio, RESULT_SUCCESS, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, dahdi_pvt::sig_pvt, SUB_REAL, analog_pvt::subs, and dahdi_pvt::subs.

Referenced by restart_monitor().

11746 {
11747    int count, res, res2, spoint, pollres=0;
11748    struct dahdi_pvt *i;
11749    struct dahdi_pvt *last = NULL;
11750    struct dahdi_pvt *doomed;
11751    time_t thispass = 0, lastpass = 0;
11752    int found;
11753    char buf[1024];
11754    struct pollfd *pfds=NULL;
11755    int lastalloc = -1;
11756    /* This thread monitors all the frame relay interfaces which are not yet in use
11757       (and thus do not have a separate thread) indefinitely */
11758    /* From here on out, we die whenever asked */
11759 #if 0
11760    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11761       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11762       return NULL;
11763    }
11764    ast_debug(1, "Monitor starting...\n");
11765 #endif
11766    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11767 
11768    pthread_cleanup_push(monitor_pfds_clean, &pfds);
11769    for (;;) {
11770       /* Lock the interface list */
11771       ast_mutex_lock(&iflock);
11772       if (!pfds || (lastalloc != ifcount)) {
11773          if (pfds) {
11774             ast_free(pfds);
11775             pfds = NULL;
11776          }
11777          if (ifcount) {
11778             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11779                ast_mutex_unlock(&iflock);
11780                return NULL;
11781             }
11782          }
11783          lastalloc = ifcount;
11784       }
11785       /* Build the stuff we're going to poll on, that is the socket of every
11786          dahdi_pvt that does not have an associated owner channel */
11787       count = 0;
11788       for (i = iflist; i; i = i->next) {
11789          ast_mutex_lock(&i->lock);
11790          if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11791             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11792                struct analog_pvt *p = i->sig_pvt;
11793 
11794                if (!p) {
11795                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11796                } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11797                   /* This needs to be watched, as it lacks an owner */
11798                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11799                   pfds[count].events = POLLPRI;
11800                   pfds[count].revents = 0;
11801                   /* Message waiting or r2 channels also get watched for reading */
11802                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11803                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11804                      pfds[count].events |= POLLIN;
11805                   }
11806                   count++;
11807                }
11808             } else {
11809                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11810                   /* This needs to be watched, as it lacks an owner */
11811                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11812                   pfds[count].events = POLLPRI;
11813                   pfds[count].revents = 0;
11814                   /* If we are monitoring for VMWI or sending CID, we need to
11815                      read from the channel as well */
11816                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11817                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11818                      pfds[count].events |= POLLIN;
11819                   }
11820                   count++;
11821                }
11822             }
11823          }
11824          ast_mutex_unlock(&i->lock);
11825       }
11826       /* Okay, now that we know what to do, release the interface lock */
11827       ast_mutex_unlock(&iflock);
11828 
11829       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11830       pthread_testcancel();
11831       /* Wait at least a second for something to happen */
11832       res = poll(pfds, count, 1000);
11833       pthread_testcancel();
11834       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11835 
11836       /* Okay, poll has finished.  Let's see what happened.  */
11837       if (res < 0) {
11838          if ((errno != EAGAIN) && (errno != EINTR))
11839             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11840          continue;
11841       }
11842       /* Alright, lock the interface list again, and let's look and see what has
11843          happened */
11844       ast_mutex_lock(&iflock);
11845       found = 0;
11846       spoint = 0;
11847       lastpass = thispass;
11848       thispass = time(NULL);
11849       doomed = NULL;
11850       for (i = iflist;; i = i->next) {
11851          if (doomed) {
11852             int res;
11853             res = dahdi_destroy_channel_bynum(doomed->channel);
11854             if (res != RESULT_SUCCESS) {
11855                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11856             }
11857             doomed = NULL;
11858          }
11859          if (!i) {
11860             break;
11861          }
11862 
11863          if (thispass != lastpass) {
11864             if (!found && ((i == last) || ((i == iflist) && !last))) {
11865                last = i;
11866                if (last) {
11867                   struct analog_pvt *analog_p = last->sig_pvt;
11868                   /* Only allow MWI to be initiated on a quiescent fxs port */
11869                   if (analog_p
11870                      && !last->mwisendactive
11871                      && (last->sig & __DAHDI_SIG_FXO)
11872                      && !analog_p->fxsoffhookstate
11873                      && !last->owner
11874                      && !ast_strlen_zero(last->mailbox)
11875                      && (thispass - analog_p->onhooktime > 3)) {
11876                      res = has_voicemail(last);
11877                      if (analog_p->msgstate != res) {
11878                         /* Set driver resources for signalling VMWI */
11879                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11880                         if (res2) {
11881                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11882                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11883                         }
11884                         /* If enabled for FSK spill then initiate it */
11885                         if (mwi_send_init(last)) {
11886                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11887                         }
11888                         analog_p->msgstate = res;
11889                         found ++;
11890                      }
11891                   }
11892                   last = last->next;
11893                }
11894             }
11895          }
11896          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11897             if (i->radio && !i->owner)
11898             {
11899                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11900                if (res)
11901                {
11902                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11903                   /* Don't hold iflock while handling init events */
11904                   ast_mutex_unlock(&iflock);
11905                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11906                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11907                   else
11908                      doomed = handle_init_event(i, res);
11909                   ast_mutex_lock(&iflock);
11910                }
11911                continue;
11912             }
11913             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11914             if (pollres & POLLIN) {
11915                if (i->owner || i->subs[SUB_REAL].owner) {
11916 #ifdef HAVE_PRI
11917                   if (!i->pri)
11918 #endif
11919                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11920                   continue;
11921                }
11922                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11923                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11924                   continue;
11925                }
11926                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11927                if (res > 0) {
11928                   if (i->mwimonitor_fsk) {
11929                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11930                         pthread_attr_t attr;
11931                         pthread_t threadid;
11932                         struct mwi_thread_data *mtd;
11933 
11934                         pthread_attr_init(&attr);
11935                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11936 
11937                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11938                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11939                            mtd->pvt = i;
11940                            memcpy(mtd->buf, buf, res);
11941                            mtd->len = res;
11942                            i->mwimonitoractive = 1;
11943                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11944                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11945                               i->mwimonitoractive = 0;
11946                               ast_free(mtd);
11947                            }
11948                         }
11949                      }
11950                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11951                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11952                      int energy;
11953                      struct timeval now;
11954                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11955                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11956                      */
11957                      if (1 == i->dtmfcid_holdoff_state) {
11958                         gettimeofday(&i->dtmfcid_delay, NULL);
11959                         i->dtmfcid_holdoff_state = 2;
11960                      } else if (2 == i->dtmfcid_holdoff_state) {
11961                         gettimeofday(&now, NULL);
11962                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11963                            i->dtmfcid_holdoff_state = 0;
11964                         }
11965                      } else {
11966                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11967                         if (!i->mwisendactive && energy > dtmfcid_level) {
11968                            pthread_t threadid;
11969                            struct ast_channel *chan;
11970                            ast_mutex_unlock(&iflock);
11971                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11972                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11973                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11974                               i->dtmfcid_holdoff_state = 1;
11975                            } else {
11976                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11977                               if (!chan) {
11978                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11979                               } else {
11980                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11981                                  if (res) {
11982                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11983                                     ast_hangup(chan);
11984                                  } else {
11985                                     i->dtmfcid_holdoff_state = 1;
11986                                  }
11987                               }
11988                            }
11989                            ast_mutex_lock(&iflock);
11990                         }
11991                      }
11992                   }
11993                   if (i->mwisendactive) {
11994                      mwi_send_process_buffer(i, res);
11995                   }
11996                } else {
11997                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11998                }
11999             }
12000             if (pollres & POLLPRI) {
12001                if (i->owner || i->subs[SUB_REAL].owner) {
12002 #ifdef HAVE_PRI
12003                   if (!i->pri)
12004 #endif
12005                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
12006                   continue;
12007                }
12008                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12009                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
12010                /* Don't hold iflock while handling init events */
12011                ast_mutex_unlock(&iflock);
12012                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
12013                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
12014                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12015                   else
12016                      doomed = handle_init_event(i, res);
12017                }
12018                ast_mutex_lock(&iflock);
12019             }
12020          }
12021       }
12022       ast_mutex_unlock(&iflock);
12023    }
12024    /* Never reached */
12025    pthread_cleanup_pop(1);
12026    return NULL;
12027 
12028 }

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

Definition at line 5007 of file chan_dahdi.c.

Referenced by fill_rxgain(), and fill_txgain().

05008 {
05009    float neg;
05010    float shallow, steep;
05011    float max = SHRT_MAX;
05012    
05013    neg = (sample < 0 ? -1 : 1);
05014    steep = drc*sample;
05015    shallow = neg*(max-max/drc)+(float)sample/drc;
05016    if (abs(steep) < abs(shallow)) {
05017       sample = steep;
05018    }
05019    else {
05020       sample = shallow;
05021    }
05022 
05023    return sample;
05024 }

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

Definition at line 13496 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(), dahdi_pvt::destroy, destroy_dahdi_pvt(), dahdi_subchannel::dfd, errno, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, dahdi_pvt::next, dahdi_pvt::prev, SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::which_iflist.

Referenced by dahdi_request().

13497 {
13498    struct dahdi_pvt *p;
13499    struct dahdi_bufferinfo bi;
13500    int res;
13501 
13502    p = ast_malloc(sizeof(*p));
13503    if (!p) {
13504       return NULL;
13505    }
13506    *p = *src;
13507 
13508    /* Must deep copy the cc_params. */
13509    p->cc_params = ast_cc_config_params_init();
13510    if (!p->cc_params) {
13511       ast_free(p);
13512       return NULL;
13513    }
13514    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13515 
13516    p->which_iflist = DAHDI_IFLIST_NONE;
13517    p->next = NULL;
13518    p->prev = NULL;
13519    ast_mutex_init(&p->lock);
13520    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13521    if (p->subs[SUB_REAL].dfd < 0) {
13522       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13523       destroy_dahdi_pvt(p);
13524       return NULL;
13525    }
13526    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13527    if (!res) {
13528       bi.txbufpolicy = src->buf_policy;
13529       bi.rxbufpolicy = src->buf_policy;
13530       bi.numbufs = src->buf_no;
13531       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13532       if (res < 0) {
13533          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13534       }
13535    } else
13536       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13537    p->destroy = 1;
13538    dahdi_iflist_insert(p);
13539    return p;
13540 }

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 6691 of file chan_dahdi.c.

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

Referenced by dahdi_bridge(), and dahdi_setoption().

06692 {
06693    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06694 
06695    if (p->channel == CHAN_PSEUDO)
06696       return;
06697 
06698    p->ignoredtmf = 0;
06699 
06700    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06701 
06702    if (!p->hardwaredtmf && p->dsp) {
06703       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06704       ast_dsp_set_features(p->dsp, p->dsp_features);
06705    }
06706 }

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

Definition at line 4659 of file chan_dahdi.c.

References ARRAY_LEN.

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

04660 {
04661    static char buf[256];
04662    if ((event < (ARRAY_LEN(events))) && (event > -1))
04663       return events[event];
04664    sprintf(buf, "Event %d", event); /* safe */
04665    return buf;
04666 }

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

Definition at line 5077 of file chan_dahdi.c.

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

Referenced by set_actual_rxgain().

05078 {
05079    int j;
05080    int k;
05081    float linear_gain = pow(10.0, gain / 20.0);
05082 
05083    switch (law) {
05084    case DAHDI_LAW_ALAW:
05085       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05086          if (gain || drc) {
05087             k = AST_ALAW(j);
05088             if (drc) {
05089                k = drc_sample(k, drc);
05090             }
05091             k = (float)k * linear_gain;
05092             if (k > 32767) {
05093                k = 32767;
05094             } else if (k < -32768) {
05095                k = -32768;
05096             }
05097             g->rxgain[j] = AST_LIN2A(k);
05098          } else {
05099             g->rxgain[j] = j;
05100          }
05101       }
05102       break;
05103    case DAHDI_LAW_MULAW:
05104       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05105          if (gain || drc) {
05106             k = AST_MULAW(j);
05107             if (drc) {
05108                k = drc_sample(k, drc);
05109             }
05110             k = (float)k * linear_gain;
05111             if (k > 32767) {
05112                k = 32767;
05113             } else if (k < -32768) {
05114                k = -32768;
05115             }
05116             g->rxgain[j] = AST_LIN2MU(k);
05117          } else {
05118             g->rxgain[j] = j;
05119          }
05120       }
05121       break;
05122    }
05123 }

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

Definition at line 5027 of file chan_dahdi.c.

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

Referenced by set_actual_txgain().

05028 {
05029    int j;
05030    int k;
05031 
05032    float linear_gain = pow(10.0, gain / 20.0);
05033 
05034    switch (law) {
05035    case DAHDI_LAW_ALAW:
05036       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05037          if (gain || drc) {
05038             k = AST_ALAW(j);
05039             if (drc) {
05040                k = drc_sample(k, drc);
05041             }
05042             k = (float)k * linear_gain;
05043             if (k > 32767) {
05044                k = 32767;
05045             } else if (k < -32768) {
05046                k = -32768;
05047             }
05048             g->txgain[j] = AST_LIN2A(k);
05049          } else {
05050             g->txgain[j] = j;
05051          }
05052       }
05053       break;
05054    case DAHDI_LAW_MULAW:
05055       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05056          if (gain || drc) {
05057             k = AST_MULAW(j);
05058             if (drc) {
05059                k = drc_sample(k, drc);
05060             }
05061             k = (float)k * linear_gain;
05062             if (k > 32767) {
05063                k = 32767;
05064             } else if (k < -32768) {
05065                k = -32768;
05066             }
05067             g->txgain[j] = AST_LIN2MU(k);
05068 
05069          } else {
05070             g->txgain[j] = j;
05071          }
05072       }
05073       break;
05074    }
05075 }

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

Definition at line 16074 of file chan_dahdi.c.

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

Referenced by find_channel_from_str().

16075 {
16076    struct dahdi_pvt *p;
16077 
16078    ast_mutex_lock(&iflock);
16079    for (p = iflist; p; p = p->next) {
16080       if (p->channel == channel) {
16081          break;
16082       }
16083    }
16084    ast_mutex_unlock(&iflock);
16085    return p;
16086 }

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

Definition at line 16097 of file chan_dahdi.c.

References find_channel().

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

16098 {
16099    int chan_num;
16100 
16101    if (sscanf(channel, "%30d", &chan_num) != 1) {
16102       /* Not numeric string. */
16103       return NULL;
16104    }
16105 
16106    return find_channel(chan_num);
16107 }

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

Definition at line 5767 of file chan_dahdi.c.

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

Referenced by destroy_dahdi_pvt().

05768 {
05769    if (cur->next && cur->next->span == cur->span) {
05770       return cur->next;
05771    } else if (cur->prev && cur->prev->span == cur->span) {
05772       return cur->prev;
05773    }
05774 
05775    return NULL;
05776 }

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

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

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

07764 {
07765    int res;
07766    struct dahdi_spaninfo zi;
07767    struct dahdi_params params;
07768 
07769    memset(&zi, 0, sizeof(zi));
07770    zi.spanno = p->span;
07771 
07772    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07773       if (zi.alarms != DAHDI_ALARM_NONE)
07774          return zi.alarms;
07775    } else {
07776       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07777       return 0;
07778    }
07779 
07780    /* No alarms on the span. Check for channel alarms. */
07781    memset(&params, 0, sizeof(params));
07782    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07783       return params.chan_alarms;
07784 
07785    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07786 
07787    return DAHDI_ALARM_NONE;
07788 }

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

Definition at line 7888 of file chan_dahdi.c.

References alarm2str(), ast_log(), dahdi_pvt::channel, dahdi_sig_pri_lib_handles(), EVENT_FLAG_SYSTEM, LOG_WARNING, manager_event, dahdi_pvt::manages_span_alarms, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, dahdi_pvt::sig, sig_pri_is_alarm_ignored(), and dahdi_pvt::span.

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

07889 {
07890    const char *alarm_str;
07891 
07892 #if defined(HAVE_PRI)
07893    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07894       return;
07895    }
07896 #endif   /* defined(HAVE_PRI) */
07897 
07898    alarm_str = alarm2str(alms);
07899    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07900       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07901       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07902                  "Alarm: %s\r\n"
07903                  "Channel: %d\r\n",
07904                  alarm_str, p->channel);
07905    }
07906 
07907    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07908       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07909       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07910                  "Alarm: %s\r\n"
07911                  "Span: %d\r\n",
07912                  alarm_str, p->span);
07913    }
07914 }

static void handle_clear_alarms ( struct dahdi_pvt p  )  [static]

Definition at line 3873 of file chan_dahdi.c.

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

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

03874 {
03875 #if defined(HAVE_PRI)
03876    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03877       return;
03878    }
03879 #endif   /* defined(HAVE_PRI) */
03880 
03881    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03882       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03883       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03884    }
03885    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03886       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03887       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03888    }
03889 }

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

Definition at line 15680 of file chan_dahdi.c.

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

15681 {
15682    int i, j;
15683    switch (cmd) {
15684    case CLI_INIT:
15685       e->command = "dahdi show cadences";
15686       e->usage =
15687          "Usage: dahdi show cadences\n"
15688          "       Shows all cadences currently defined\n";
15689       return NULL;
15690    case CLI_GENERATE:
15691       return NULL;
15692    }
15693    for (i = 0; i < num_cadence; i++) {
15694       char output[1024];
15695       char tmp[16], tmp2[64];
15696       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15697       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15698 
15699       for (j = 0; j < 16; j++) {
15700          if (cadences[i].ringcadence[j] == 0)
15701             break;
15702          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15703          if (cidrings[i] * 2 - 1 == j)
15704             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15705          else
15706             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15707          if (j != 0)
15708             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15709          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15710       }
15711       ast_cli(a->fd,"%s\n",output);
15712    }
15713    return CLI_SUCCESS;
15714 }

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

Definition at line 11493 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(), dahdi_subchannel::dfd, errno, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, 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.

Referenced by do_monitor().

11494 {
11495    int res;
11496    pthread_t threadid;
11497    struct ast_channel *chan;
11498 
11499    /* Handle an event on a given channel for the monitor thread. */
11500 
11501    switch (event) {
11502    case DAHDI_EVENT_NONE:
11503    case DAHDI_EVENT_BITSCHANGED:
11504       break;
11505    case DAHDI_EVENT_WINKFLASH:
11506    case DAHDI_EVENT_RINGOFFHOOK:
11507       if (i->inalarm) break;
11508       if (i->radio) break;
11509       /* Got a ring/answer.  What kind of channel are we? */
11510       switch (i->sig) {
11511       case SIG_FXOLS:
11512       case SIG_FXOGS:
11513       case SIG_FXOKS:
11514          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11515          if (res && (errno == EBUSY))
11516             break;
11517 
11518          /* Cancel VMWI spill */
11519          ast_free(i->cidspill);
11520          i->cidspill = NULL;
11521          restore_conference(i);
11522 
11523          if (i->immediate) {
11524             dahdi_enable_ec(i);
11525             /* The channel is immediately up.  Start right away */
11526             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11527             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11528             if (!chan) {
11529                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11530                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11531                if (res < 0)
11532                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11533             }
11534          } else {
11535             /* Check for callerid, digits, etc */
11536             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11537             if (chan) {
11538                if (has_voicemail(i))
11539                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11540                else
11541                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11542                if (res < 0)
11543                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11544                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11545                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11546                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11547                   if (res < 0)
11548                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11549                   ast_hangup(chan);
11550                }
11551             } else
11552                ast_log(LOG_WARNING, "Unable to create channel\n");
11553          }
11554          break;
11555       case SIG_FXSLS:
11556       case SIG_FXSGS:
11557       case SIG_FXSKS:
11558             i->ringt = i->ringt_base;
11559             /* Fall through */
11560       case SIG_EMWINK:
11561       case SIG_FEATD:
11562       case SIG_FEATDMF:
11563       case SIG_FEATDMF_TA:
11564       case SIG_E911:
11565       case SIG_FGC_CAMA:
11566       case SIG_FGC_CAMAMF:
11567       case SIG_FEATB:
11568       case SIG_EM:
11569       case SIG_EM_E1:
11570       case SIG_SFWINK:
11571       case SIG_SF_FEATD:
11572       case SIG_SF_FEATDMF:
11573       case SIG_SF_FEATB:
11574       case SIG_SF:
11575          /* Check for callerid, digits, etc */
11576          if (i->cid_start == CID_START_POLARITY_IN) {
11577             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11578          } else {
11579             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11580          }
11581 
11582          if (!chan) {
11583             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11584          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11585             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11586             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11587             if (res < 0) {
11588                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11589             }
11590             ast_hangup(chan);
11591          }
11592          break;
11593       default:
11594          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11595          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11596          if (res < 0)
11597             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11598          return NULL;
11599       }
11600       break;
11601    case DAHDI_EVENT_NOALARM:
11602       switch (i->sig) {
11603 #if defined(HAVE_PRI)
11604       case SIG_PRI_LIB_HANDLE_CASES:
11605          ast_mutex_lock(&i->lock);
11606          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11607          ast_mutex_unlock(&i->lock);
11608          break;
11609 #endif   /* defined(HAVE_PRI) */
11610 #if defined(HAVE_SS7)
11611       case SIG_SS7:
11612          sig_ss7_set_alarm(i->sig_pvt, 0);
11613          break;
11614 #endif   /* defined(HAVE_SS7) */
11615       default:
11616          i->inalarm = 0;
11617          break;
11618       }
11619       handle_clear_alarms(i);
11620       break;
11621    case DAHDI_EVENT_ALARM:
11622       switch (i->sig) {
11623 #if defined(HAVE_PRI)
11624       case SIG_PRI_LIB_HANDLE_CASES:
11625          ast_mutex_lock(&i->lock);
11626          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11627          ast_mutex_unlock(&i->lock);
11628          break;
11629 #endif   /* defined(HAVE_PRI) */
11630 #if defined(HAVE_SS7)
11631       case SIG_SS7:
11632          sig_ss7_set_alarm(i->sig_pvt, 1);
11633          break;
11634 #endif   /* defined(HAVE_SS7) */
11635       default:
11636          i->inalarm = 1;
11637          break;
11638       }
11639       res = get_alarms(i);
11640       handle_alarms(i, res);
11641       /* fall thru intentionally */
11642    case DAHDI_EVENT_ONHOOK:
11643       if (i->radio)
11644          break;
11645       /* Back on hook.  Hang up. */
11646       switch (i->sig) {
11647       case SIG_FXOLS:
11648       case SIG_FXOGS:
11649       case SIG_FEATD:
11650       case SIG_FEATDMF:
11651       case SIG_FEATDMF_TA:
11652       case SIG_E911:
11653       case SIG_FGC_CAMA:
11654       case SIG_FGC_CAMAMF:
11655       case SIG_FEATB:
11656       case SIG_EM:
11657       case SIG_EM_E1:
11658       case SIG_EMWINK:
11659       case SIG_SF_FEATD:
11660       case SIG_SF_FEATDMF:
11661       case SIG_SF_FEATB:
11662       case SIG_SF:
11663       case SIG_SFWINK:
11664       case SIG_FXSLS:
11665       case SIG_FXSGS:
11666       case SIG_FXSKS:
11667       case SIG_FXOKS:
11668          dahdi_disable_ec(i);
11669          /* Diddle the battery for the zhone */
11670 #ifdef ZHONE_HACK
11671          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11672          usleep(1);
11673 #endif
11674          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11675          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11676          break;
11677       case SIG_SS7:
11678       case SIG_PRI_LIB_HANDLE_CASES:
11679          dahdi_disable_ec(i);
11680          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11681          break;
11682       default:
11683          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11684          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11685          return NULL;
11686       }
11687       break;
11688    case DAHDI_EVENT_POLARITY:
11689       switch (i->sig) {
11690       case SIG_FXSLS:
11691       case SIG_FXSKS:
11692       case SIG_FXSGS:
11693          /* We have already got a PR before the channel was
11694             created, but it wasn't handled. We need polarity
11695             to be REV for remote hangup detection to work.
11696             At least in Spain */
11697          if (i->hanguponpolarityswitch)
11698             i->polarity = POLARITY_REV;
11699          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11700             i->polarity = POLARITY_REV;
11701             ast_verb(2, "Starting post polarity "
11702                "CID detection on channel %d\n",
11703                i->channel);
11704             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11705             if (!chan) {
11706                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11707             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11708                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11709                ast_hangup(chan);
11710             }
11711          }
11712          break;
11713       default:
11714          ast_log(LOG_WARNING, "handle_init_event detected "
11715             "polarity reversal on non-FXO (SIG_FXS) "
11716             "interface %d\n", i->channel);
11717       }
11718       break;
11719    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11720       ast_log(LOG_NOTICE,
11721             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11722             i->channel);
11723       return i;
11724    case DAHDI_EVENT_NEONMWI_ACTIVE:
11725       if (i->mwimonitor_neon) {
11726          notify_message(i->mailbox, 1);
11727          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11728       }
11729       break;
11730    case DAHDI_EVENT_NEONMWI_INACTIVE:
11731       if (i->mwimonitor_neon) {
11732          notify_message(i->mailbox, 0);
11733          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11734       }
11735       break;
11736    }
11737    return NULL;
11738 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

Definition at line 5302 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, and mailbox.

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

05303 {
05304    int new_msgs;
05305    struct ast_event *event;
05306    char *mailbox, *context;
05307 
05308    mailbox = context = ast_strdupa(p->mailbox);
05309    strsep(&context, "@");
05310    if (ast_strlen_zero(context))
05311       context = "default";
05312 
05313    event = ast_event_get_cached(AST_EVENT_MWI,
05314       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05315       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05316       AST_EVENT_IE_END);
05317 
05318    if (event) {
05319       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05320       ast_event_destroy(event);
05321    } else
05322       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05323 
05324    return new_msgs;
05325 }

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

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

Referenced by dahdi_cc_callback(), and dahdi_request().

13256 {
13257 #if defined(HAVE_PRI)
13258    if (0 < span) {
13259       /* The channel must be on the specified PRI span. */
13260       if (!p->pri || p->pri->span != span) {
13261          return 0;
13262       }
13263       if (!groupmatch && channelmatch == -1) {
13264          /* Match any group since it only needs to be on the PRI span. */
13265          *groupmatched = 1;
13266          return 1;
13267       }
13268    }
13269 #endif   /* defined(HAVE_PRI) */
13270    /* check group matching */
13271    if (groupmatch) {
13272       if ((p->group & groupmatch) != groupmatch)
13273          /* Doesn't match the specified group, try the next one */
13274          return 0;
13275       *groupmatched = 1;
13276    }
13277    /* Check to see if we have a channel match */
13278    if (channelmatch != -1) {
13279       if (p->channel != channelmatch)
13280          /* Doesn't match the specified channel, try the next one */
13281          return 0;
13282       *channelmatched = 1;
13283    }
13284 
13285    return 1;
13286 }

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

Definition at line 4772 of file chan_dahdi.c.

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

Referenced by conf_del().

04773 {
04774    /* If they're listening to our channel, they're ours */
04775    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04776       return 1;
04777    /* If they're a talker on our (allocated) conference, they're ours */
04778    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04779       return 1;
04780    return 0;
04781 }

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

Definition at line 4802 of file chan_dahdi.c.

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

Referenced by my_complete_conference_update(), and update_conf().

04803 {
04804    int x;
04805    int useslavenative;
04806    struct dahdi_pvt *slave = NULL;
04807    /* Start out optimistic */
04808    useslavenative = 1;
04809    /* Update conference state in a stateless fashion */
04810    for (x = 0; x < 3; x++) {
04811       /* Any three-way calling makes slave native mode *definitely* out
04812          of the question */
04813       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04814          useslavenative = 0;
04815    }
04816    /* If we don't have any 3-way calls, check to see if we have
04817       precisely one slave */
04818    if (useslavenative) {
04819       for (x = 0; x < MAX_SLAVES; x++) {
04820          if (p->slaves[x]) {
04821             if (slave) {
04822                /* Whoops already have a slave!  No
04823                   slave native and stop right away */
04824                slave = NULL;
04825                useslavenative = 0;
04826                break;
04827             } else {
04828                /* We have one slave so far */
04829                slave = p->slaves[x];
04830             }
04831          }
04832       }
04833    }
04834    /* If no slave, slave native definitely out */
04835    if (!slave)
04836       useslavenative = 0;
04837    else if (slave->law != p->law) {
04838       useslavenative = 0;
04839       slave = NULL;
04840    }
04841    if (out)
04842       *out = slave;
04843    return useslavenative;
04844 }

static int load_module ( void   )  [static]

Definition at line 18756 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, HAVE_PRI_CCSS, LOG_ERROR, setup_dahdi(), sig_pri_init_pri(), sig_pri_load(), and sig_ss7_init_linkset().

18757 {
18758    int res;
18759 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18760    int y;
18761 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18762 
18763 #ifdef HAVE_PRI
18764    memset(pris, 0, sizeof(pris));
18765    for (y = 0; y < NUM_SPANS; y++) {
18766       sig_pri_init_pri(&pris[y].pri);
18767    }
18768    pri_set_error(dahdi_pri_error);
18769    pri_set_message(dahdi_pri_message);
18770    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18771 #ifdef HAVE_PRI_PROG_W_CAUSE
18772    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18773 #endif
18774 #if defined(HAVE_PRI_CCSS)
18775    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18776       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18777       __unload_module();
18778       return AST_MODULE_LOAD_FAILURE;
18779    }
18780 #endif   /* defined(HAVE_PRI_CCSS) */
18781    if (sig_pri_load(
18782 #if defined(HAVE_PRI_CCSS)
18783       dahdi_pri_cc_type
18784 #else
18785       NULL
18786 #endif   /* defined(HAVE_PRI_CCSS) */
18787       )) {
18788       __unload_module();
18789       return AST_MODULE_LOAD_FAILURE;
18790    }
18791 #endif
18792 #if defined(HAVE_SS7)
18793    memset(linksets, 0, sizeof(linksets));
18794    for (y = 0; y < NUM_SPANS; y++) {
18795       sig_ss7_init_linkset(&linksets[y].ss7);
18796    }
18797    ss7_set_error(dahdi_ss7_error);
18798    ss7_set_message(dahdi_ss7_message);
18799 #endif   /* defined(HAVE_SS7) */
18800    res = setup_dahdi(0);
18801    /* Make sure we can register our DAHDI channel type */
18802    if (res)
18803       return AST_MODULE_LOAD_DECLINE;
18804    if (ast_channel_register(&dahdi_tech)) {
18805       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18806       __unload_module();
18807       return AST_MODULE_LOAD_FAILURE;
18808    }
18809 #ifdef HAVE_PRI
18810    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18811 #endif
18812 #if defined(HAVE_SS7)
18813    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18814 #endif   /* defined(HAVE_SS7) */
18815 #ifdef HAVE_OPENR2
18816    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18817    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18818 #endif
18819 
18820    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18821    /* register all the data providers */
18822    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18823    memset(round_robin, 0, sizeof(round_robin));
18824    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18825    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18826    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18827    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18828    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18829    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18830    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18831 
18832    ast_cond_init(&ss_thread_complete, NULL);
18833 
18834    return res;
18835 }

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

< Current channel structure initializing

< TRUE if the channel interface already exists.

Definition at line 12364 of file chan_dahdi.c.

References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, ANALOG_CID_START_DTMF_NOALERT, ANALOG_CID_START_POLARITY, ANALOG_CID_START_POLARITY_IN, ANALOG_CID_START_RING, analog_config_complete(), analog_lib_handles(), analog_new(), ANALOG_SIG_NONE, analog_pvt::answeronpolarityswitch, dahdi_pvt::answeronpolarityswitch, ARRAY_LEN, ast_calloc, ast_cc_config_params_init, ast_cc_copy_config_params(), ast_copy_string(), ast_db_del(), ast_db_get(), ast_debug, ast_dsp_set_digitmode(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_free, ast_log(), ast_mutex_init, ast_smdi_interface_find(), ast_strdupa, ast_strlen_zero(), ast_variable_new(), ast_variables_destroy(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufsize, dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::callgroup, dahdi_pvt::callprogress, analog_pvt::callreturn, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, analog_pvt::callwaitingcallerid, dahdi_pvt::callwaitingcallerid, analog_pvt::cancallforward, dahdi_pvt::cancallforward, analog_pvt::canpark, dahdi_pvt::canpark, dahdi_pvt::cc_params, dahdi_chan_conf::chan, CHAN_PSEUDO, analog_pvt::channel, sig_pri_chan::channel, sig_ss7_chan::channel, dahdi_pvt::channel, sig_ss7_chan::cic, analog_pvt::cid_name, dahdi_pvt::cid_name, analog_pvt::cid_num, dahdi_pvt::cid_num, dahdi_pvt::cid_rxgain, CID_SIG_SMDI, analog_pvt::cid_signalling, dahdi_pvt::cid_signalling, analog_pvt::cid_start, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_tag, dahdi_pvt::cid_ton, dahdi_pvt::confno, sig_ss7_chan::context, sig_pri_chan::context, context, dahdi_pvt::context, dahdi_iflist_insert(), dahdi_open(), dahdi_set_hook(), dahdi_sig2str(), dahdi_sig_pri_lib_handles(), dahdisig_to_analogsig(), analog_pvt::dahditrcallerid, dahdi_pvt::dahditrcallerid, dahdi_pvt::defcontext, dahdi_pvt::destroy, destroy_dahdi_pvt(), dahdi_subchannel::dfd, sig_pri_span::dialplan, sig_ss7_chan::dpc, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, analog_pvt::echotraining, dahdi_pvt::echotraining, errno, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, ast_variable::file, dahdi_pvt::firstradio, analog_pvt::fxsoffhookstate, get_alarms(), dahdi_pvt::group, handle_alarms(), analog_pvt::hanguponpolarityswitch, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::head, sig_ss7_chan::hidecallerid, sig_pri_chan::hidecallerid, dahdi_pvt::hidecallerid, sig_pri_chan::hidecalleridname, dahdi_pvt::hidecalleridname, sig_pri_span::idledial, sig_pri_span::idleext, analog_pvt::immediate, sig_ss7_chan::immediate, sig_pri_chan::immediate, dahdi_pvt::immediate, sig_ss7_chan::inalarm, sig_pri_chan::inalarm, dahdi_pvt::inalarm, analog_pvt::inalarm, dahdi_pvt::inservice, dahdi_chan_conf::is_sig_auto, dahdi_pvt::language, dahdi_pvt::law, dahdi_pvt::law_default, sig_ss7_chan::locallyblocked, dahdi_pvt::locallyblocked, dahdi_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, mailbox, dahdi_pvt::mailbox, sig_pri_span::minidle, sig_pri_span::minunused, sig_ss7_chan::mohinterpret, sig_pri_chan::mohinterpret, dahdi_pvt::mohinterpret, analog_pvt::mohsuggest, dahdi_pvt::mohsuggest, analog_pvt::msgstate, mwi_event_cb(), dahdi_pvt::mwi_event_sub, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, ast_variable::name, ast_variable::next, dahdi_pvt::next, sig_pri_span::nodetype, sig_pri_span::numchans, analog_pvt::onhooktime, dahdi_pvt::oprmode, analog_pvt::outsigmod, dahdi_pvt::outsigmod, dahdi_pvt::parkinglot, analog_pvt::permcallwaiting, dahdi_pvt::permcallwaiting, analog_pvt::permhidecallerid, dahdi_pvt::permhidecallerid, dahdi_pvt::pickupgroup, analog_pvt::polarityonanswerdelay, dahdi_pvt::polarityonanswerdelay, sig_pri_chan::priexclusive, dahdi_pvt::priexclusive, sig_pri_chan::priindication_oob, dahdi_pvt::priindication_oob, dahdi_pvt::propconfno, analog_pvt::pulse, dahdi_pvt::pulse, sig_pri_span::pvts, dahdi_pvt::radio, distRingData::range, sig_ss7_chan::remotelyblocked, dahdi_pvt::remotelyblocked, dahdi_pvt::restrictcid, dahdi_distRings::ringnum, dahdi_pvt::ringt, analog_pvt::ringt, analog_pvt::ringt_base, dahdi_pvt::ringt_base, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, set_actual_gain(), dahdi_pvt::sig, sig2str, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, sig_pri_chan_new(), SIG_PRI_LIB_HANDLE_CASES, sig_pri_set_alarm(), dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sig_ss7_chan_new(), sig_ss7_set_alarm(), sigtype_to_signalling(), dahdi_pvt::silencethreshold, analog_pvt::smdi_iface, dahdi_pvt::smdi_iface, dahdi_chan_conf::smdi_port, dahdi_pvt::span, analog_pvt::stripmsd, sig_ss7_chan::stripmsd, sig_pri_chan::stripmsd, dahdi_pvt::stripmsd, SUB_REAL, dahdi_pvt::subs, sig_pri_span::switchtype, analog_pvt::threewaycalling, dahdi_pvt::threewaycalling, dahdi_chan_conf::timing, dahdi_pvt::tonezone, analog_pvt::transfer, dahdi_pvt::transfer, analog_pvt::transfertobusy, dahdi_pvt::transfertobusy, sig_pri_span::trunkgroup, dahdi_pvt::txdrc, dahdi_pvt::txgain, update_conf(), analog_pvt::use_callerid, sig_ss7_chan::use_callerid, sig_pri_chan::use_callerid, dahdi_pvt::use_callerid, sig_ss7_chan::use_callingpres, sig_pri_chan::use_callingpres, dahdi_pvt::use_callingpres, analog_pvt::use_smdi, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, dahdi_pvt::usefaxbuffers, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

Referenced by build_channels(), and process_dahdi().

12365 {
12366    /* Make a dahdi_pvt structure for this interface */
12367    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12368    char fn[80];
12369    struct dahdi_bufferinfo bi;
12370 
12371    int res;
12372 #if defined(HAVE_PRI)
12373    int span = 0;
12374 #endif   /* defined(HAVE_PRI) */
12375    int here = 0;/*!< TRUE if the channel interface already exists. */
12376    int x;
12377    struct analog_pvt *analog_p = NULL;
12378    struct dahdi_params p;
12379 #if defined(HAVE_PRI)
12380    struct dahdi_spaninfo si;
12381    struct sig_pri_chan *pri_chan = NULL;
12382 #endif   /* defined(HAVE_PRI) */
12383 #if defined(HAVE_SS7)
12384    struct sig_ss7_chan *ss7_chan = NULL;
12385 #endif   /* defined(HAVE_SS7) */
12386 
12387    /* Search channel interface list to see if it already exists. */
12388    for (tmp = iflist; tmp; tmp = tmp->next) {
12389       if (!tmp->destroy) {
12390          if (tmp->channel == channel) {
12391             /* The channel interface already exists. */
12392             here = 1;
12393             break;
12394          }
12395          if (tmp->channel > channel) {
12396             /* No way it can be in the sorted list. */
12397             tmp = NULL;
12398             break;
12399          }
12400       }
12401    }
12402 
12403    if (!here && reloading != 1) {
12404       tmp = ast_calloc(1, sizeof(*tmp));
12405       if (!tmp) {
12406          return NULL;
12407       }
12408       tmp->cc_params = ast_cc_config_params_init();
12409       if (!tmp->cc_params) {
12410          ast_free(tmp);
12411          return NULL;
12412       }
12413       ast_mutex_init(&tmp->lock);
12414       ifcount++;
12415       for (x = 0; x < 3; x++)
12416          tmp->subs[x].dfd = -1;
12417       tmp->channel = channel;
12418       tmp->priindication_oob = conf->chan.priindication_oob;
12419    }
12420 
12421    if (tmp) {
12422       int chan_sig = conf->chan.sig;
12423 
12424       /* If there are variables in tmp before it is updated to match the new config, clear them */
12425       if (reloading && tmp->vars) {
12426          ast_variables_destroy(tmp->vars);
12427          tmp->vars = NULL;
12428       }
12429 
12430 
12431       if (!here) {
12432          /* Can only get here if this is a new channel interface being created. */
12433          if ((channel != CHAN_PSEUDO)) {
12434             int count = 0;
12435 
12436             snprintf(fn, sizeof(fn), "%d", channel);
12437             /* Open non-blocking */
12438             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12439             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 */
12440                usleep(1);
12441                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12442                count++;
12443             }
12444             /* Allocate a DAHDI structure */
12445             if (tmp->subs[SUB_REAL].dfd < 0) {
12446                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);
12447                destroy_dahdi_pvt(tmp);
12448                return NULL;
12449             }
12450             memset(&p, 0, sizeof(p));
12451             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12452             if (res < 0) {
12453                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12454                destroy_dahdi_pvt(tmp);
12455                return NULL;
12456             }
12457             if (conf->is_sig_auto)
12458                chan_sig = sigtype_to_signalling(p.sigtype);
12459             if (p.sigtype != (chan_sig & 0x3ffff)) {
12460                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));
12461                destroy_dahdi_pvt(tmp);
12462                return NULL;
12463             }
12464             tmp->law_default = p.curlaw;
12465             tmp->law = p.curlaw;
12466             tmp->span = p.spanno;
12467 #if defined(HAVE_PRI)
12468             span = p.spanno - 1;
12469 #endif   /* defined(HAVE_PRI) */
12470          } else {
12471             chan_sig = 0;
12472          }
12473          tmp->sig = chan_sig;
12474          tmp->outsigmod = conf->chan.outsigmod;
12475 
12476          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12477             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12478             if (!analog_p) {
12479                destroy_dahdi_pvt(tmp);
12480                return NULL;
12481             }
12482             tmp->sig_pvt = analog_p;
12483          }
12484 #if defined(HAVE_SS7)
12485          if (chan_sig == SIG_SS7) {
12486             struct dahdi_ss7 *ss7;
12487             int clear = 0;
12488 
12489             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12490                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12491                destroy_dahdi_pvt(tmp);
12492                return NULL;
12493             }
12494 
12495             ss7 = ss7_resolve_linkset(cur_linkset);
12496             if (!ss7) {
12497                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12498                destroy_dahdi_pvt(tmp);
12499                return NULL;
12500             }
12501             ss7->ss7.span = cur_linkset;
12502             if (cur_cicbeginswith < 0) {
12503                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12504                destroy_dahdi_pvt(tmp);
12505                return NULL;
12506             }
12507             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12508             if (!ss7_chan) {
12509                destroy_dahdi_pvt(tmp);
12510                return NULL;
12511             }
12512             tmp->sig_pvt = ss7_chan;
12513             tmp->ss7 = &ss7->ss7;
12514 
12515             ss7_chan->channel = tmp->channel;
12516             ss7_chan->cic = cur_cicbeginswith++;
12517 
12518             /* DB: Add CIC's DPC information */
12519             ss7_chan->dpc = cur_defaultdpc;
12520 
12521             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12522 
12523             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12524             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12525             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12526             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12527 
12528             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12529             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12530          }
12531 #endif   /* defined(HAVE_SS7) */
12532 #ifdef HAVE_OPENR2
12533          if (chan_sig == SIG_MFCR2) {
12534             struct dahdi_mfcr2 *r2_link;
12535             r2_link = dahdi_r2_get_link(conf);
12536             if (!r2_link) {
12537                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12538                destroy_dahdi_pvt(tmp);
12539                return NULL;
12540             }
12541             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12542                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12543                destroy_dahdi_pvt(tmp);
12544                return NULL;
12545             }
12546             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12547                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12548                destroy_dahdi_pvt(tmp);
12549                return NULL;
12550             }
12551             r2_link->pvts[r2_link->numchans++] = tmp;
12552             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12553                                         tmp->subs[SUB_REAL].dfd,
12554                                         NULL, NULL);
12555             if (!tmp->r2chan) {
12556                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12557                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12558                destroy_dahdi_pvt(tmp);
12559                return NULL;
12560             }
12561             tmp->mfcr2 = r2_link;
12562             if (conf->mfcr2.call_files) {
12563                openr2_chan_enable_call_files(tmp->r2chan);
12564             }
12565             openr2_chan_set_client_data(tmp->r2chan, tmp);
12566             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12567             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12568             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12569             tmp->mfcr2_category = conf->mfcr2.category;
12570             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12571             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12572             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12573             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12574             tmp->mfcr2call = 0;
12575             tmp->mfcr2_dnis_index = 0;
12576             tmp->mfcr2_ani_index = 0;
12577          }
12578 #endif
12579 #ifdef HAVE_PRI
12580          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12581             int offset;
12582             int matchesdchan;
12583             int x,y;
12584             int myswitchtype = 0;
12585 
12586             offset = 0;
12587             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12588                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12589                destroy_dahdi_pvt(tmp);
12590                return NULL;
12591             }
12592             if (span >= NUM_SPANS) {
12593                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12594                destroy_dahdi_pvt(tmp);
12595                return NULL;
12596             } else {
12597                si.spanno = 0;
12598                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12599                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12600                   destroy_dahdi_pvt(tmp);
12601                   return NULL;
12602                }
12603                /* Store the logical span first based upon the real span */
12604                tmp->logicalspan = pris[span].prilogicalspan;
12605                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12606                if (span < 0) {
12607                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12608                   destroy_dahdi_pvt(tmp);
12609                   return NULL;
12610                }
12611                myswitchtype = conf->pri.pri.switchtype;
12612                /* Make sure this isn't a d-channel */
12613                matchesdchan=0;
12614                for (x = 0; x < NUM_SPANS; x++) {
12615                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12616                      if (pris[x].dchannels[y] == tmp->channel) {
12617                         matchesdchan = 1;
12618                         break;
12619                      }
12620                   }
12621                }
12622                if (!matchesdchan) {
12623                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12624                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12625                      destroy_dahdi_pvt(tmp);
12626                      return NULL;
12627                   }
12628                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12629                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12630                      destroy_dahdi_pvt(tmp);
12631                      return NULL;
12632                   }
12633                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12634                      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));
12635                      destroy_dahdi_pvt(tmp);
12636                      return NULL;
12637                   }
12638                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12639                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12640                      destroy_dahdi_pvt(tmp);
12641                      return NULL;
12642                   }
12643                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12644                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12645                      destroy_dahdi_pvt(tmp);
12646                      return NULL;
12647                   }
12648                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12649                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12650                      destroy_dahdi_pvt(tmp);
12651                      return NULL;
12652                   }
12653                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12654                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12655                      destroy_dahdi_pvt(tmp);
12656                      return NULL;
12657                   }
12658                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12659                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12660                         pris[span].pri.trunkgroup);
12661                      destroy_dahdi_pvt(tmp);
12662                      return NULL;
12663                   }
12664 
12665                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12666                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12667                   if (!pri_chan) {
12668                      destroy_dahdi_pvt(tmp);
12669                      return NULL;
12670                   }
12671                   tmp->sig_pvt = pri_chan;
12672                   tmp->pri = &pris[span].pri;
12673 
12674                   tmp->priexclusive = conf->chan.priexclusive;
12675 
12676                   if (!tmp->pri->cc_params) {
12677                      tmp->pri->cc_params = ast_cc_config_params_init();
12678                      if (!tmp->pri->cc_params) {
12679                         destroy_dahdi_pvt(tmp);
12680                         return NULL;
12681                      }
12682                   }
12683                   ast_cc_copy_config_params(tmp->pri->cc_params,
12684                      conf->chan.cc_params);
12685 
12686                   pris[span].pri.sig = chan_sig;
12687                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12688                   pris[span].pri.switchtype = myswitchtype;
12689                   pris[span].pri.nsf = conf->pri.pri.nsf;
12690                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12691                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12692                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12693                   pris[span].pri.minunused = conf->pri.pri.minunused;
12694                   pris[span].pri.minidle = conf->pri.pri.minidle;
12695                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12696                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12697                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12698 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12699                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12700 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12701 #ifdef HAVE_PRI_INBANDDISCONNECT
12702                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12703 #endif
12704 #if defined(HAVE_PRI_CALL_HOLD)
12705                   pris[span].pri.hold_disconnect_transfer =
12706                      conf->pri.pri.hold_disconnect_transfer;
12707 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12708 #if defined(HAVE_PRI_CCSS)
12709                   pris[span].pri.cc_ptmp_recall_mode =
12710                      conf->pri.pri.cc_ptmp_recall_mode;
12711                   pris[span].pri.cc_qsig_signaling_link_req =
12712                      conf->pri.pri.cc_qsig_signaling_link_req;
12713                   pris[span].pri.cc_qsig_signaling_link_rsp =
12714                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12715 #endif   /* defined(HAVE_PRI_CCSS) */
12716 #if defined(HAVE_PRI_CALL_WAITING)
12717                   pris[span].pri.max_call_waiting_calls =
12718                      conf->pri.pri.max_call_waiting_calls;
12719                   pris[span].pri.allow_call_waiting_calls =
12720                      conf->pri.pri.allow_call_waiting_calls;
12721 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12722                   pris[span].pri.transfer = conf->chan.transfer;
12723                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12724 #if defined(HAVE_PRI_L2_PERSISTENCE)
12725                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12726 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12727 #if defined(HAVE_PRI_AOC_EVENTS)
12728                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12729                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12730 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12731                   if (chan_sig == SIG_BRI_PTMP) {
12732                      pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12733                   } else {
12734                      /* Option does not apply to this line type. */
12735                      pris[span].pri.layer1_ignored = 0;
12736                   }
12737                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12738                   pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack;
12739                   pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12740                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12741                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12742 #if defined(HAVE_PRI_MWI)
12743                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12744                      conf->pri.pri.mwi_mailboxes,
12745                      sizeof(pris[span].pri.mwi_mailboxes));
12746 #endif   /* defined(HAVE_PRI_MWI) */
12747                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12748                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12749                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12750                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12751                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12752                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12753                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12754                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12755 
12756                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12757                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12758                   }
12759 
12760 #if defined(HAVE_PRI_CALL_WAITING)
12761                   /* Channel initial config parameters. */
12762                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12763                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12764                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12765                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12766                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12767                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12768                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12769                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12770                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12771                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12772 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12773                } else {
12774                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12775                   destroy_dahdi_pvt(tmp);
12776                   return NULL;
12777                }
12778             }
12779          }
12780 #endif
12781       } else {
12782          /* already exists in interface list */
12783          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));
12784          chan_sig = tmp->sig;
12785          if (tmp->subs[SUB_REAL].dfd > -1) {
12786             memset(&p, 0, sizeof(p));
12787             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12788          }
12789       }
12790       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12791       switch (chan_sig) {
12792       case SIG_FXSKS:
12793       case SIG_FXSLS:
12794       case SIG_EM:
12795       case SIG_EM_E1:
12796       case SIG_EMWINK:
12797       case SIG_FEATD:
12798       case SIG_FEATDMF:
12799       case SIG_FEATDMF_TA:
12800       case SIG_FEATB:
12801       case SIG_E911:
12802       case SIG_SF:
12803       case SIG_SFWINK:
12804       case SIG_FGC_CAMA:
12805       case SIG_FGC_CAMAMF:
12806       case SIG_SF_FEATD:
12807       case SIG_SF_FEATDMF:
12808       case SIG_SF_FEATB:
12809          p.starttime = 250;
12810          break;
12811       }
12812 
12813       if (tmp->radio) {
12814          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12815          p.channo = channel;
12816          p.rxwinktime = 1;
12817          p.rxflashtime = 1;
12818          p.starttime = 1;
12819          p.debouncetime = 5;
12820       } else {
12821          p.channo = channel;
12822          /* Override timing settings based on config file */
12823          if (conf->timing.prewinktime >= 0)
12824             p.prewinktime = conf->timing.prewinktime;
12825          if (conf->timing.preflashtime >= 0)
12826             p.preflashtime = conf->timing.preflashtime;
12827          if (conf->timing.winktime >= 0)
12828             p.winktime = conf->timing.winktime;
12829          if (conf->timing.flashtime >= 0)
12830             p.flashtime = conf->timing.flashtime;
12831          if (conf->timing.starttime >= 0)
12832             p.starttime = conf->timing.starttime;
12833          if (conf->timing.rxwinktime >= 0)
12834             p.rxwinktime = conf->timing.rxwinktime;
12835          if (conf->timing.rxflashtime >= 0)
12836             p.rxflashtime = conf->timing.rxflashtime;
12837          if (conf->timing.debouncetime >= 0)
12838             p.debouncetime = conf->timing.debouncetime;
12839       }
12840 
12841       /* don't set parms on a pseudo-channel */
12842       if (tmp->subs[SUB_REAL].dfd >= 0)
12843       {
12844          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12845          if (res < 0) {
12846             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12847             destroy_dahdi_pvt(tmp);
12848             return NULL;
12849          }
12850       }
12851 #if 1
12852       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12853          memset(&bi, 0, sizeof(bi));
12854          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12855          if (!res) {
12856             bi.txbufpolicy = conf->chan.buf_policy;
12857             bi.rxbufpolicy = conf->chan.buf_policy;
12858             bi.numbufs = conf->chan.buf_no;
12859             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12860             if (res < 0) {
12861                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12862             }
12863          } else {
12864             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12865          }
12866          tmp->buf_policy = conf->chan.buf_policy;
12867          tmp->buf_no = conf->chan.buf_no;
12868          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12869          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12870          tmp->faxbuf_no = conf->chan.faxbuf_no;
12871          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12872           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12873           * The reason the ioctl call above failed should to be determined before worrying about the
12874           * faxbuffer-related ioctl calls */
12875          tmp->bufsize = bi.bufsize;
12876       }
12877 #endif
12878       tmp->immediate = conf->chan.immediate;
12879       tmp->transfertobusy = conf->chan.transfertobusy;
12880       if (chan_sig & __DAHDI_SIG_FXS) {
12881          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12882          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12883          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12884       }
12885       tmp->ringt_base = ringt_base;
12886       tmp->firstradio = 0;
12887       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12888          tmp->permcallwaiting = conf->chan.callwaiting;
12889       else
12890          tmp->permcallwaiting = 0;
12891       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12892       tmp->destroy = 0;
12893       tmp->drings = conf->chan.drings;
12894 
12895       /* 10 is a nice default. */
12896       if (tmp->drings.ringnum[0].range == 0)
12897          tmp->drings.ringnum[0].range = 10;
12898       if (tmp->drings.ringnum[1].range == 0)
12899          tmp->drings.ringnum[1].range = 10;
12900       if (tmp->drings.ringnum[2].range == 0)
12901          tmp->drings.ringnum[2].range = 10;
12902 
12903       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12904       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12905       tmp->threewaycalling = conf->chan.threewaycalling;
12906       tmp->adsi = conf->chan.adsi;
12907       tmp->use_smdi = conf->chan.use_smdi;
12908       tmp->permhidecallerid = conf->chan.hidecallerid;
12909       tmp->hidecalleridname = conf->chan.hidecalleridname;
12910       tmp->callreturn = conf->chan.callreturn;
12911       tmp->echocancel = conf->chan.echocancel;
12912       tmp->echotraining = conf->chan.echotraining;
12913       tmp->pulse = conf->chan.pulse;
12914       if (tmp->echocancel.head.tap_length) {
12915          tmp->echocanbridged = conf->chan.echocanbridged;
12916       } else {
12917          if (conf->chan.echocanbridged)
12918             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12919          tmp->echocanbridged = 0;
12920       }
12921       tmp->busydetect = conf->chan.busydetect;
12922       tmp->busycount = conf->chan.busycount;
12923       tmp->busycompare = conf->chan.busycompare;
12924       tmp->busytonelength = conf->chan.busytonelength;
12925       tmp->busyquietlength = conf->chan.busyquietlength;
12926       tmp->busyfuzziness = conf->chan.busyfuzziness;
12927       tmp->silencethreshold = conf->chan.silencethreshold;
12928       tmp->callprogress = conf->chan.callprogress;
12929       tmp->waitfordialtone = conf->chan.waitfordialtone;
12930       tmp->cancallforward = conf->chan.cancallforward;
12931       tmp->dtmfrelax = conf->chan.dtmfrelax;
12932       tmp->callwaiting = tmp->permcallwaiting;
12933       tmp->hidecallerid = tmp->permhidecallerid;
12934       tmp->channel = channel;
12935       tmp->stripmsd = conf->chan.stripmsd;
12936       tmp->use_callerid = conf->chan.use_callerid;
12937       tmp->cid_signalling = conf->chan.cid_signalling;
12938       tmp->cid_start = conf->chan.cid_start;
12939       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12940       tmp->restrictcid = conf->chan.restrictcid;
12941       tmp->use_callingpres = conf->chan.use_callingpres;
12942       if (tmp->usedistinctiveringdetection) {
12943          if (!tmp->use_callerid) {
12944             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12945             tmp->use_callerid = 1;
12946          }
12947       }
12948 
12949       if (tmp->cid_signalling == CID_SIG_SMDI) {
12950          if (!tmp->use_smdi) {
12951             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12952             tmp->use_smdi = 1;
12953          }
12954       }
12955       if (tmp->use_smdi) {
12956          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12957          if (!(tmp->smdi_iface)) {
12958             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12959             tmp->use_smdi = 0;
12960          }
12961       }
12962 
12963       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12964       tmp->amaflags = conf->chan.amaflags;
12965       if (!here) {
12966          tmp->confno = -1;
12967          tmp->propconfno = -1;
12968       }
12969       tmp->canpark = conf->chan.canpark;
12970       tmp->transfer = conf->chan.transfer;
12971       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12972       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12973       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12974       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12975       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12976       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12977       tmp->cid_ton = 0;
12978       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12979          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12980          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12981       } else {
12982          tmp->cid_num[0] = '\0';
12983          tmp->cid_name[0] = '\0';
12984       }
12985 #if defined(HAVE_PRI)
12986       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12987          tmp->cid_tag[0] = '\0';
12988       } else
12989 #endif   /* defined(HAVE_PRI) */
12990       {
12991          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12992       }
12993       tmp->cid_subaddr[0] = '\0';
12994       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12995       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12996          char *mailbox, *context;
12997          mailbox = context = ast_strdupa(tmp->mailbox);
12998          strsep(&context, "@");
12999          if (ast_strlen_zero(context))
13000             context = "default";
13001          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
13002             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
13003             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
13004             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
13005             AST_EVENT_IE_END);
13006       }
13007 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13008       tmp->mwisend_setting = conf->chan.mwisend_setting;
13009       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
13010       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
13011 #endif
13012 
13013       tmp->group = conf->chan.group;
13014       tmp->callgroup = conf->chan.callgroup;
13015       tmp->pickupgroup= conf->chan.pickupgroup;
13016       if (conf->chan.vars) {
13017          struct ast_variable *v, *tmpvar;
13018                    for (v = conf->chan.vars ; v ; v = v->next) {
13019                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
13020                                   tmpvar->next = tmp->vars;
13021                                    tmp->vars = tmpvar;
13022                            }
13023                   }
13024       }
13025       tmp->cid_rxgain = conf->chan.cid_rxgain;
13026       tmp->rxgain = conf->chan.rxgain;
13027       tmp->txgain = conf->chan.txgain;
13028       tmp->txdrc = conf->chan.txdrc;
13029       tmp->rxdrc = conf->chan.rxdrc;
13030       tmp->tonezone = conf->chan.tonezone;
13031       if (tmp->subs[SUB_REAL].dfd > -1) {
13032          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13033          if (tmp->dsp)
13034             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13035          update_conf(tmp);
13036          if (!here) {
13037             switch (chan_sig) {
13038             case SIG_PRI_LIB_HANDLE_CASES:
13039             case SIG_SS7:
13040             case SIG_MFCR2:
13041                break;
13042             default:
13043                /* Hang it up to be sure it's good */
13044                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13045                break;
13046             }
13047          }
13048          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13049          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13050             /* the dchannel is down so put the channel in alarm */
13051             switch (tmp->sig) {
13052 #ifdef HAVE_PRI
13053             case SIG_PRI_LIB_HANDLE_CASES:
13054                sig_pri_set_alarm(tmp->sig_pvt, 1);
13055                break;
13056 #endif
13057 #if defined(HAVE_SS7)
13058             case SIG_SS7:
13059                sig_ss7_set_alarm(tmp->sig_pvt, 1);
13060                break;
13061 #endif   /* defined(HAVE_SS7) */
13062             default:
13063                /* The only sig submodule left should be sig_analog. */
13064                analog_p = tmp->sig_pvt;
13065                if (analog_p) {
13066                   analog_p->inalarm = 1;
13067                }
13068                tmp->inalarm = 1;
13069                break;
13070             }
13071             handle_alarms(tmp, res);
13072          }
13073       }
13074 
13075       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13076       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13077       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13078       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13079       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13080 
13081       if (!here) {
13082          tmp->locallyblocked = 0;
13083          tmp->remotelyblocked = 0;
13084          switch (tmp->sig) {
13085 #if defined(HAVE_PRI)
13086          case SIG_PRI_LIB_HANDLE_CASES:
13087             tmp->inservice = 1;/* Inservice until actually implemented. */
13088 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13089             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13090             if (chan_sig == SIG_PRI) {
13091                char db_chan_name[20];
13092                char db_answer[5];
13093 
13094                /*
13095                 * Initialize the active out-of-service status
13096                 * and delete any record if the feature is not enabled.
13097                 */
13098                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13099                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13100                   unsigned *why;
13101 
13102                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13103                   if (tmp->pri->enable_service_message_support) {
13104                      char state;
13105 
13106                      sscanf(db_answer, "%1c:%30u", &state, why);
13107 
13108                      /* Ensure that only the implemented bits could be set.*/
13109                      *why &= (SRVST_NEAREND | SRVST_FAREND);
13110                   }
13111                   if (!*why) {
13112                      ast_db_del(db_chan_name, SRVST_DBKEY);
13113                   }
13114                }
13115             }
13116 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13117             break;
13118 #endif   /* defined(HAVE_PRI) */
13119 #if defined(HAVE_SS7)
13120          case SIG_SS7:
13121             tmp->inservice = 0;
13122             break;
13123 #endif   /* defined(HAVE_SS7) */
13124          default:
13125              /* We default to in service on protocols that don't have a reset */
13126             tmp->inservice = 1;
13127             break;
13128          }
13129       }
13130 
13131       switch (tmp->sig) {
13132 #if defined(HAVE_PRI)
13133       case SIG_PRI_LIB_HANDLE_CASES:
13134          if (pri_chan) {
13135             pri_chan->channel = tmp->channel;
13136             pri_chan->hidecallerid = tmp->hidecallerid;
13137             pri_chan->hidecalleridname = tmp->hidecalleridname;
13138             pri_chan->immediate = tmp->immediate;
13139             pri_chan->inalarm = tmp->inalarm;
13140             pri_chan->priexclusive = tmp->priexclusive;
13141             pri_chan->priindication_oob = tmp->priindication_oob;
13142             pri_chan->use_callerid = tmp->use_callerid;
13143             pri_chan->use_callingpres = tmp->use_callingpres;
13144             ast_copy_string(pri_chan->context, tmp->context,
13145                sizeof(pri_chan->context));
13146             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13147                sizeof(pri_chan->mohinterpret));
13148             pri_chan->stripmsd = tmp->stripmsd;
13149          }
13150          break;
13151 #endif   /* defined(HAVE_PRI) */
13152 #if defined(HAVE_SS7)
13153       case SIG_SS7:
13154          if (ss7_chan) {
13155             ss7_chan->inalarm = tmp->inalarm;
13156 
13157             ss7_chan->stripmsd = tmp->stripmsd;
13158             ss7_chan->hidecallerid = tmp->hidecallerid;
13159             ss7_chan->use_callerid = tmp->use_callerid;
13160             ss7_chan->use_callingpres = tmp->use_callingpres;
13161             ss7_chan->immediate = tmp->immediate;
13162             ss7_chan->locallyblocked = tmp->locallyblocked;
13163             ss7_chan->remotelyblocked = tmp->remotelyblocked;
13164             ast_copy_string(ss7_chan->context, tmp->context,
13165                sizeof(ss7_chan->context));
13166             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13167                sizeof(ss7_chan->mohinterpret));
13168          }
13169          break;
13170 #endif   /* defined(HAVE_SS7) */
13171       default:
13172          /* The only sig submodule left should be sig_analog. */
13173          analog_p = tmp->sig_pvt;
13174          if (analog_p) {
13175             analog_p->channel = tmp->channel;
13176             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13177             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13178             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13179             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13180             analog_p->callreturn = conf->chan.callreturn;
13181             analog_p->cancallforward = conf->chan.cancallforward;
13182             analog_p->canpark = conf->chan.canpark;
13183             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13184             analog_p->immediate = conf->chan.immediate;
13185             analog_p->permhidecallerid = conf->chan.permhidecallerid;
13186             analog_p->pulse = conf->chan.pulse;
13187             analog_p->threewaycalling = conf->chan.threewaycalling;
13188             analog_p->transfer = conf->chan.transfer;
13189             analog_p->transfertobusy = conf->chan.transfertobusy;
13190             analog_p->use_callerid = tmp->use_callerid;
13191             analog_p->use_smdi = tmp->use_smdi;
13192             analog_p->smdi_iface = tmp->smdi_iface;
13193             analog_p->outsigmod = ANALOG_SIG_NONE;
13194             analog_p->echotraining = conf->chan.echotraining;
13195             analog_p->cid_signalling = conf->chan.cid_signalling;
13196             analog_p->stripmsd = conf->chan.stripmsd;
13197             switch (conf->chan.cid_start) {
13198             case CID_START_POLARITY:
13199                analog_p->cid_start = ANALOG_CID_START_POLARITY;
13200                break;
13201             case CID_START_POLARITY_IN:
13202                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13203                break;
13204             case CID_START_DTMF_NOALERT:
13205                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13206                break;
13207             default:
13208                analog_p->cid_start = ANALOG_CID_START_RING;
13209                break;
13210             }
13211             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13212             analog_p->ringt = conf->chan.ringt;
13213             analog_p->ringt_base = ringt_base;
13214             analog_p->onhooktime = time(NULL);
13215             if (chan_sig & __DAHDI_SIG_FXO) {
13216                memset(&p, 0, sizeof(p));
13217                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13218                if (!res) {
13219                   analog_p->fxsoffhookstate = p.rxisoffhook;
13220                }
13221 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13222                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13223 #endif
13224             }
13225             analog_p->msgstate = -1;
13226 
13227             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13228             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13229             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13230 
13231             analog_config_complete(analog_p);
13232          }
13233          break;
13234       }
13235 #if defined(HAVE_PRI)
13236       if (tmp->channel == CHAN_PSEUDO) {
13237          /*
13238           * Save off pseudo channel buffer policy values for dynamic creation of
13239           * no B channel interfaces.
13240           */
13241          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13242          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13243          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13244          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13245       }
13246 #endif   /* defined(HAVE_PRI) */
13247    }
13248    if (tmp && !here) {
13249       /* Add the new channel interface to the sorted channel interface list. */
13250       dahdi_iflist_insert(tmp);
13251    }
13252    return tmp;
13253 }

static void monitor_pfds_clean ( void *  arg  )  [static]

Definition at line 11740 of file chan_dahdi.c.

References ast_free.

Referenced by do_monitor().

11740                                           {
11741    struct pollfd **pfds = arg;
11742    ast_free(*pfds);
11743 }

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

Definition at line 486 of file chan_dahdi.c.

Referenced by mkintf().

00487 {
00488    /* This module does not handle MWI in an event-based manner.  However, it
00489     * subscribes to MWI for each mailbox that is configured so that the core
00490     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00491     * event cache instead of checking the mailbox directly. */
00492 }

static int mwi_send_init ( struct dahdi_pvt pvt  )  [static]

Definition at line 11287 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, dahdi_subchannel::dfd, has_voicemail(), LOG_WARNING, MAX_CALLERID_SIZE, MWI_SEND_SA, MWI_SEND_SPILL, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, SUB_REAL, and dahdi_pvt::subs.

Referenced by do_monitor().

11288 {
11289    int x;
11290 
11291 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11292    /* Determine how this spill is to be sent */
11293    if (pvt->mwisend_rpas) {
11294       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11295       pvt->mwisendactive = 1;
11296    } else if (pvt->mwisend_fsk) {
11297       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11298       pvt->mwisendactive = 1;
11299    } else {
11300       pvt->mwisendactive = 0;
11301       return 0;
11302    }
11303 #else
11304    if (mwisend_rpas) {
11305       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11306    } else {
11307       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11308    }
11309    pvt->mwisendactive = 1;
11310 #endif
11311 
11312    if (pvt->cidspill) {
11313       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11314       ast_free(pvt->cidspill);
11315       pvt->cidspill = NULL;
11316       pvt->cidpos = 0;
11317       pvt->cidlen = 0;
11318    }
11319    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11320    if (!pvt->cidspill) {
11321       pvt->mwisendactive = 0;
11322       return -1;
11323    }
11324    x = DAHDI_FLUSH_BOTH;
11325    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11326    x = 3000;
11327    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11328 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11329    if (pvt->mwisend_fsk) {
11330 #endif
11331       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11332                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11333       pvt->cidpos = 0;
11334 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11335    }
11336 #endif
11337    return 0;
11338 }

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

Definition at line 11340 of file chan_dahdi.c.

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

Referenced by do_monitor().

11341 {
11342    struct timeval    now;
11343    int         res;
11344 
11345    /* sanity check to catch if this had been interrupted previously
11346    *  i.e. state says there is more to do but there is no spill allocated
11347    */
11348    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11349       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11350    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11351       /* Normal processing -- Perform mwi send action */
11352       switch ( pvt->mwisend_data.mwisend_current) {
11353       case MWI_SEND_SA:
11354          /* Send the Ring Pulse Signal Alert */
11355          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11356          if (res) {
11357             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11358             goto quit;
11359          }
11360          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11361          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11362          break;
11363       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11364          break;
11365       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11366 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11367          if (pvt->mwisend_fsk) {
11368 #endif
11369             gettimeofday(&now, NULL);
11370             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11371                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11372             }
11373 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11374          } else { /* support for mwisendtype=nofsk */
11375             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11376          }
11377 #endif
11378          break;
11379       case MWI_SEND_SPILL:
11380          /* We read some number of bytes.  Write an equal amount of data */
11381          if(0 < num_read) {
11382             if (num_read > pvt->cidlen - pvt->cidpos)
11383                num_read = pvt->cidlen - pvt->cidpos;
11384             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11385             if (res > 0) {
11386                pvt->cidpos += res;
11387                if (pvt->cidpos >= pvt->cidlen) {
11388                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11389                }
11390             } else {
11391                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11392                goto quit;
11393             }
11394          }
11395          break;
11396       case MWI_SEND_CLEANUP:
11397          /* For now, do nothing */
11398          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11399          break;
11400       default:
11401          /* Should not get here, punt*/
11402          goto quit;
11403       }
11404    }
11405 
11406    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11407       if (pvt->cidspill) {
11408          ast_free(pvt->cidspill);
11409          pvt->cidspill = NULL;
11410          pvt->cidpos = 0;
11411          pvt->cidlen = 0;
11412       }
11413       pvt->mwisendactive = 0;
11414    }
11415    return 0;
11416 quit:
11417    if (pvt->cidspill) {
11418       ast_free(pvt->cidspill);
11419       pvt->cidspill = NULL;
11420       pvt->cidpos = 0;
11421       pvt->cidlen = 0;
11422    }
11423    pvt->mwisendactive = 0;
11424    return -1;
11425 }

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

Definition at line 11427 of file chan_dahdi.c.

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

Referenced by do_monitor().

11428 {
11429    int handled = 0;
11430 
11431    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11432       switch (event) {
11433       case DAHDI_EVENT_RINGEROFF:
11434          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11435             handled = 1;
11436 
11437             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11438                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11439                ast_free(pvt->cidspill);
11440                pvt->cidspill = NULL;
11441                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11442                pvt->mwisendactive = 0;
11443             } else {
11444                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11445                gettimeofday(&pvt->mwisend_data.pause, NULL);
11446             }
11447          }
11448          break;
11449       /* Going off hook, I need to punt this spill */
11450       case DAHDI_EVENT_RINGOFFHOOK:
11451          if (pvt->cidspill) {
11452             ast_free(pvt->cidspill);
11453             pvt->cidspill = NULL;
11454             pvt->cidpos = 0;
11455             pvt->cidlen = 0;
11456          }
11457          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11458          pvt->mwisendactive = 0;
11459          break;
11460       case DAHDI_EVENT_RINGERON:
11461       case DAHDI_EVENT_HOOKCOMPLETE:
11462          break;
11463       default:
11464          break;
11465       }
11466    }
11467    return handled;
11468 }

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

Definition at line 11135 of file chan_dahdi.c.

References analog_lib_handles(), analog_ss_thread(), analog_ss_thread_start(), ast_free, ast_hangup(), AST_LAW, ast_log(), ast_pthread_create_detached, AST_STATE_RING, mwi_thread_data::buf, bump_gains(), calc_energy(), callerid_feed(), callerid_free(), callerid_get(), callerid_new(), dahdi_pvt::channel, CID_MSGWAITING, CID_NOMSGWAITING, dahdi_pvt::cid_signalling, dahdi_get_event(), dahdi_new(), dahdi_subchannel::dfd, errno, event2str(), callerid_state::flags, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::inalarm, analog_pvt::inalarm, mwi_thread_data::len, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::mwimonitoractive, name, notify_message(), 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.

Referenced by do_monitor().

11136 {
11137    struct mwi_thread_data *mtd = data;
11138    struct callerid_state *cs;
11139    pthread_t threadid;
11140    int samples = 0;
11141    char *name, *number;
11142    int flags;
11143    int i, res;
11144    unsigned int spill_done = 0;
11145    int spill_result = -1;
11146 
11147    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11148       goto quit_no_clean;
11149    }
11150 
11151    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11152 
11153    bump_gains(mtd->pvt);
11154 
11155    for (;;) {
11156       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11157       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11158          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11159          goto quit;
11160       }
11161 
11162       if (i & DAHDI_IOMUX_SIGEVENT) {
11163          struct ast_channel *chan;
11164 
11165          /* If we get an event, screen out events that we do not act on.
11166           * Otherwise, cancel and go to the simple switch to let it deal with it.
11167           */
11168          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11169 
11170          switch (res) {
11171          case DAHDI_EVENT_NEONMWI_ACTIVE:
11172          case DAHDI_EVENT_NEONMWI_INACTIVE:
11173          case DAHDI_EVENT_NONE:
11174          case DAHDI_EVENT_BITSCHANGED:
11175             break;
11176          case DAHDI_EVENT_NOALARM:
11177             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11178                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11179 
11180                analog_p->inalarm = 0;
11181             }
11182             mtd->pvt->inalarm = 0;
11183             handle_clear_alarms(mtd->pvt);
11184             break;
11185          case DAHDI_EVENT_ALARM:
11186             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11187                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11188 
11189                analog_p->inalarm = 1;
11190             }
11191             mtd->pvt->inalarm = 1;
11192             res = get_alarms(mtd->pvt);
11193             handle_alarms(mtd->pvt, res);
11194             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11195          default:
11196             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
11197             callerid_free(cs);
11198 
11199             restore_gains(mtd->pvt);
11200             mtd->pvt->ringt = mtd->pvt->ringt_base;
11201 
11202             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11203                int result;
11204 
11205                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11206                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11207                } else {
11208                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11209                }
11210                if (result) {
11211                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11212                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11213                   if (res < 0)
11214                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11215                   ast_hangup(chan);
11216                }
11217             } else {
11218                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11219             }
11220             goto quit_no_clean;
11221          }
11222       } else if (i & DAHDI_IOMUX_READ) {
11223          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11224             if (errno != ELAST) {
11225                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11226                goto quit;
11227             }
11228             break;
11229          }
11230          samples += res;
11231          if (!spill_done) {
11232             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11233                /*
11234                 * The previous diagnostic message output likely
11235                 * explains why it failed.
11236                 */
11237                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11238                break;
11239             } else if (spill_result) {
11240                spill_done = 1;
11241             }
11242          } else {
11243             /* keep reading data until the energy level drops below the threshold
11244                so we don't get another 'trigger' on the remaining carrier signal
11245             */
11246             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11247                break;
11248          }
11249          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11250             break;
11251       }
11252    }
11253 
11254    if (spill_result == 1) {
11255       callerid_get(cs, &name, &number, &flags);
11256       if (flags & CID_MSGWAITING) {
11257          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11258          notify_message(mtd->pvt->mailbox, 1);
11259       } else if (flags & CID_NOMSGWAITING) {
11260          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11261          notify_message(mtd->pvt->mailbox, 0);
11262       } else {
11263          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11264       }
11265    }
11266 
11267 
11268 quit:
11269    callerid_free(cs);
11270 
11271    restore_gains(mtd->pvt);
11272 
11273 quit_no_clean:
11274    mtd->pvt->mwimonitoractive = 0;
11275    ast_free(mtd);
11276 
11277    return NULL;
11278 }

static void my_all_subchannels_hungup ( void *  pvt  )  [static]

Definition at line 2459 of file chan_dahdi.c.

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

02460 {
02461    struct dahdi_pvt *p = pvt;
02462    int res, law;
02463 
02464    p->faxhandled = 0;
02465    p->didtdd = 0;
02466 
02467    if (p->dsp) {
02468       ast_dsp_free(p->dsp);
02469       p->dsp = NULL;
02470    }
02471 
02472    p->law = p->law_default;
02473    law = p->law_default;
02474    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02475    if (res < 0)
02476       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02477 
02478    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02479 
02480 #if 1
02481    {
02482    int i;
02483    p->owner = NULL;
02484    /* Cleanup owners here */
02485    for (i = 0; i < 3; i++) {
02486       p->subs[i].owner = NULL;
02487    }
02488    }
02489 #endif
02490 
02491    reset_conf(p);
02492    if (num_restart_pending == 0) {
02493       restart_monitor();
02494    }
02495 }

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

Definition at line 2770 of file chan_dahdi.c.

References alloc_sub(), and analogsub_to_dahdisub().

02771 {
02772    struct dahdi_pvt *p = pvt;
02773 
02774    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02775 }

static void my_answer_polarityswitch ( void *  pvt  )  [static]

Definition at line 3008 of file chan_dahdi.c.

References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().

03009 {
03010    struct dahdi_pvt *p = pvt;
03011 
03012    if (!p->answeronpolarityswitch) {
03013       return;
03014    }
03015 
03016    my_set_polarity(pvt, 1);
03017 }

static int my_callwait ( void *  pvt  )  [static]

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

01952 {
01953    struct dahdi_pvt *p = pvt;
01954    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01955    if (p->cidspill) {
01956       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01957       ast_free(p->cidspill);
01958    }
01959 
01960    /*
01961     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01962     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01963     */
01964    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01965       return -1;
01966    save_conference(p);
01967    /* Silence */
01968    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01969    if (!p->callwaitrings && p->callwaitingcallerid) {
01970       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01971       p->callwaitcas = 1;
01972       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01973    } else {
01974       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01975       p->callwaitcas = 0;
01976       p->cidlen = 2400 + READ_SIZE * 4;
01977    }
01978    p->cidpos = 0;
01979    send_callerid(p);
01980 
01981    return 0;
01982 }

static void my_cancel_cidspill ( void *  pvt  )  [static]

Definition at line 2409 of file chan_dahdi.c.

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

02410 {
02411    struct dahdi_pvt *p = pvt;
02412 
02413    ast_free(p->cidspill);
02414    p->cidspill = NULL;
02415    restore_conference(p);
02416 }

static int my_check_confirmanswer ( void *  pvt  )  [static]

Definition at line 2392 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

02393 {
02394    struct dahdi_pvt *p = pvt;
02395    if (p->confirmanswer) {
02396       return 1;
02397    }
02398 
02399    return 0;
02400 }

static int my_check_for_conference ( void *  pvt  )  [static]

Definition at line 2569 of file chan_dahdi.c.

References check_for_conference().

02570 {
02571    struct dahdi_pvt *p = pvt;
02572    return check_for_conference(p);
02573 }

static int my_check_waitingfordt ( void *  pvt  )  [static]

Definition at line 2375 of file chan_dahdi.c.

References dahdi_pvt::waitingfordt.

02376 {
02377    struct dahdi_pvt *p = pvt;
02378 
02379    if (p->waitingfordt.tv_sec) {
02380       return 1;
02381    }
02382 
02383    return 0;
02384 }

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

Definition at line 2519 of file chan_dahdi.c.

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

02520 {
02521    struct dahdi_pvt *p = pvt;
02522    int needconf = needconference;
02523    int x;
02524    int useslavenative;
02525    struct dahdi_pvt *slave = NULL;
02526 
02527    useslavenative = isslavenative(p, &slave);
02528 
02529    /* If we have a slave, add him to our conference now. or DAX
02530       if this is slave native */
02531    for (x = 0; x < MAX_SLAVES; x++) {
02532       if (p->slaves[x]) {
02533          if (useslavenative)
02534             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02535          else {
02536             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02537             needconf++;
02538          }
02539       }
02540    }
02541    /* If we're supposed to be in there, do so now */
02542    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02543       if (useslavenative)
02544          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02545       else {
02546          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02547          needconf++;
02548       }
02549    }
02550    /* If we have a master, add ourselves to his conference */
02551    if (p->master) {
02552       if (isslavenative(p->master, NULL)) {
02553          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02554       } else {
02555          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02556       }
02557    }
02558    if (!needconf) {
02559       /* Nobody is left (or should be left) in our conference.
02560          Kill it. */
02561       p->confno = -1;
02562    }
02563 
02564    return 0;
02565 }

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

Definition at line 2509 of file chan_dahdi.c.

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

02510 {
02511    struct dahdi_pvt *p = pvt;
02512    int x = analogsub_to_dahdisub(sub);
02513 
02514    return conf_add(p, &p->subs[x], x, 0);
02515 }

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

Definition at line 2499 of file chan_dahdi.c.

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

02500 {
02501    struct dahdi_pvt *p = pvt;
02502    int x = analogsub_to_dahdisub(sub);
02503 
02504    return conf_del(p, &p->subs[x], x);
02505 }

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

Definition at line 2418 of file chan_dahdi.c.

References dahdi_confmute().

02419 {
02420    struct dahdi_pvt *p = pvt;
02421    return dahdi_confmute(p, mute);
02422 }

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

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

09393 {
09394    int sent=0;
09395    int size;
09396    int res;
09397    int fd;
09398    fd = p->subs[idx].dfd;
09399    while (len) {
09400       size = len;
09401       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09402          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09403       res = write(fd, buf, size);
09404       if (res != size) {
09405          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09406          return sent;
09407       }
09408       len -= size;
09409       buf += size;
09410    }
09411    return sent;
09412 }

static void my_deadlock_avoidance_private ( void *  pvt  )  [static]

Definition at line 2169 of file chan_dahdi.c.

References DEADLOCK_AVOIDANCE, and dahdi_pvt::lock.

02170 {
02171    struct dahdi_pvt *p = pvt;
02172 
02173    DEADLOCK_AVOIDANCE(&p->lock);
02174 }

static void my_decrease_ss_count ( void   )  [static]

Definition at line 2451 of file chan_dahdi.c.

References ast_cond_signal, ast_mutex_lock, and ast_mutex_unlock.

02452 {
02453    ast_mutex_lock(&ss_thread_lock);
02454    ss_thread_count--;
02455    ast_cond_signal(&ss_thread_complete);
02456    ast_mutex_unlock(&ss_thread_lock);
02457 }

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

Definition at line 3042 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, analog_dialoperation::op, dahdi_pvt::owner, and dahdi_pvt::subs.

03043 {
03044    int index = analogsub_to_dahdisub(sub);
03045    int res;
03046    struct dahdi_pvt *p = pvt;
03047    struct dahdi_dialoperation ddop;
03048 
03049    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03050       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03051       return -1;
03052    }
03053 
03054    if (sub != ANALOG_SUB_REAL) {
03055       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
03056          dop->dialstr, p->channel, sub);
03057       return -1;
03058    }
03059 
03060    ddop.op = DAHDI_DIAL_OP_REPLACE;
03061    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03062 
03063    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03064 
03065    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03066    if (res == -1) {
03067       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03068    }
03069 
03070    return res;
03071 }

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

Definition at line 1815 of file chan_dahdi.c.

References ast_copy_string(), ast_hangup(), ast_log(), ast_verb, ast_channel::context, dahdi_pvt::context, ringContextData::contextData, dahdi_get_event(), dahdi_setlinear(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::drings, errno, event2str(), analog_pvt::inalarm, dahdi_pvt::inalarm, dahdi_subchannel::linear, LOG_NOTICE, LOG_WARNING, distRingData::range, restore_gains(), distRingData::ring, RING_PATTERNS, dahdi_distRings::ringContext, dahdi_distRings::ringnum, analog_pvt::ringt, analog_pvt::ringt_base, S_OR, dahdi_pvt::sig_pvt, and dahdi_pvt::subs.

01816 {
01817    unsigned char buf[256];
01818    int distMatches;
01819    int curRingData[RING_PATTERNS];
01820    int receivedRingT;
01821    int counter1;
01822    int counter;
01823    int i;
01824    int res;
01825    int checkaftercid = 0;
01826 
01827    struct dahdi_pvt *p = pvt;
01828    struct analog_pvt *analog_p = p->sig_pvt;
01829 
01830    if (ringdata == NULL) {
01831       ringdata = curRingData;
01832    } else {
01833       checkaftercid = 1;
01834    }
01835 
01836    /* We must have a ring by now, so, if configured, lets try to listen for
01837     * distinctive ringing */
01838    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01839       /* Clear the current ring data array so we don't have old data in it. */
01840       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01841          ringdata[receivedRingT] = 0;
01842       receivedRingT = 0;
01843       if (checkaftercid && distinctiveringaftercid)
01844          ast_verb(3, "Detecting post-CID distinctive ring\n");
01845       /* Check to see if context is what it should be, if not set to be. */
01846       else if (strcmp(p->context,p->defcontext) != 0) {
01847          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01848          ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01849       }
01850 
01851       for (;;) {
01852          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01853          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01854             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01855             ast_hangup(chan);
01856             return 1;
01857          }
01858          if (i & DAHDI_IOMUX_SIGEVENT) {
01859             res = dahdi_get_event(p->subs[idx].dfd);
01860             if (res == DAHDI_EVENT_NOALARM) {
01861                p->inalarm = 0;
01862                analog_p->inalarm = 0;
01863             }
01864             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01865             res = 0;
01866             /* Let us detect distinctive ring */
01867 
01868             ringdata[receivedRingT] = analog_p->ringt;
01869 
01870             if (analog_p->ringt < analog_p->ringt_base/2)
01871                break;
01872             /* Increment the ringT counter so we can match it against
01873                values in chan_dahdi.conf for distinctive ring */
01874             if (++receivedRingT == RING_PATTERNS)
01875                break;
01876          } else if (i & DAHDI_IOMUX_READ) {
01877             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01878             if (res < 0) {
01879                if (errno != ELAST) {
01880                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01881                   ast_hangup(chan);
01882                   return 1;
01883                }
01884                break;
01885             }
01886             if (analog_p->ringt > 0) {
01887                if (!(--analog_p->ringt)) {
01888                   res = -1;
01889                   break;
01890                }
01891             }
01892          }
01893       }
01894    }
01895    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01896       /* this only shows up if you have n of the dring patterns filled in */
01897       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01898       for (counter = 0; counter < 3; counter++) {
01899       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01900          distMatches = 0;
01901          /* this only shows up if you have n of the dring patterns filled in */
01902          ast_verb(3, "Checking %d,%d,%d\n",
01903                p->drings.ringnum[counter].ring[0],
01904                p->drings.ringnum[counter].ring[1],
01905                p->drings.ringnum[counter].ring[2]);
01906          for (counter1 = 0; counter1 < 3; counter1++) {
01907             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01908             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01909                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01910                ringdata[counter1]);
01911                distMatches++;
01912             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01913                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01914                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01915                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01916                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01917                distMatches++;
01918             }
01919          }
01920 
01921          if (distMatches == 3) {
01922             /* The ring matches, set the context to whatever is for distinctive ring.. */
01923             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01924             ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01925             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01926             break;
01927          }
01928       }
01929    }
01930    /* Restore linear mode (if appropriate) for Caller*ID processing */
01931    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01932    restore_gains(p);
01933 
01934    return 0;
01935 }

static int my_dsp_reset_and_flush_digits ( void *  pvt  )  [static]

Definition at line 2019 of file chan_dahdi.c.

References ast_dsp_digitreset(), and dahdi_pvt::dsp.

02020 {
02021    struct dahdi_pvt *p = pvt;
02022    if (p->dsp)
02023       ast_dsp_digitreset(p->dsp);
02024 
02025    return 0;
02026 }

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

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

02029 {
02030    struct dahdi_pvt *p = pvt;
02031 
02032    if (p->channel == CHAN_PSEUDO)
02033       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02034 
02035    if (mode == ANALOG_DIGITMODE_DTMF) {
02036       /* If we do hardware dtmf, no need for a DSP */
02037       if (p->hardwaredtmf) {
02038          if (p->dsp) {
02039             ast_dsp_free(p->dsp);
02040             p->dsp = NULL;
02041          }
02042          return 0;
02043       }
02044 
02045       if (!p->dsp) {
02046          p->dsp = ast_dsp_new();
02047          if (!p->dsp) {
02048             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02049             return -1;
02050          }
02051       }
02052 
02053       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02054    } else if (mode == ANALOG_DIGITMODE_MF) {
02055       if (!p->dsp) {
02056          p->dsp = ast_dsp_new();
02057          if (!p->dsp) {
02058             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02059             return -1;
02060          }
02061       }
02062       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02063    }
02064    return 0;
02065 }

static int my_flash ( void *  pvt  )  [static]

Definition at line 2967 of file chan_dahdi.c.

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

02968 {
02969    struct dahdi_pvt *p = pvt;
02970    int func = DAHDI_FLASH;
02971    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02972 }

static void my_get_and_handle_alarms ( void *  pvt  )  [static]

Definition at line 2255 of file chan_dahdi.c.

References get_alarms(), and handle_alarms().

02256 {
02257    int res;
02258    struct dahdi_pvt *p = pvt;
02259 
02260    res = get_alarms(p);
02261    handle_alarms(p, res);
02262 }

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

Definition at line 1741 of file chan_dahdi.c.

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

01742 {
01743    struct dahdi_pvt *p = pvt;
01744    struct analog_pvt *analog_p = p->sig_pvt;
01745    struct pollfd poller;
01746    char *name, *num;
01747    int index = SUB_REAL;
01748    int res;
01749    unsigned char buf[256];
01750    int flags;
01751 
01752    poller.fd = p->subs[SUB_REAL].dfd;
01753    poller.events = POLLPRI | POLLIN;
01754    poller.revents = 0;
01755 
01756    res = poll(&poller, 1, timeout);
01757 
01758    if (poller.revents & POLLPRI) {
01759       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01760       return 1;
01761    }
01762 
01763    if (poller.revents & POLLIN) {
01764       /*** NOTES ***/
01765       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01766        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01767        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01768        * a failure and die, and returning 2 means no event was received. */
01769       res = read(p->subs[index].dfd, buf, sizeof(buf));
01770       if (res < 0) {
01771          ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01772          return -1;
01773       }
01774 
01775       if (analog_p->ringt > 0) {
01776          if (!(--analog_p->ringt)) {
01777             /* only return if we timeout from a ring event */
01778             return -1;
01779          }
01780       }
01781 
01782       if (p->cid_signalling == CID_SIG_V23_JP) {
01783          res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01784       } else {
01785          res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01786       }
01787       if (res < 0) {
01788          /*
01789           * The previous diagnostic message output likely
01790           * explains why it failed.
01791           */
01792          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01793          return -1;
01794       }
01795 
01796       if (res == 1) {
01797          callerid_get(p->cs, &name, &num, &flags);
01798          if (name)
01799             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01800          if (num)
01801             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01802 
01803          ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01804          return 0;
01805       }
01806    }
01807 
01808    *ev = ANALOG_EVENT_NONE;
01809    return 2;
01810 }

static int my_get_event ( void *  pvt  )  [static]

Definition at line 2900 of file chan_dahdi.c.

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

02901 {
02902    struct dahdi_pvt *p = pvt;
02903    int res;
02904 
02905    if (p->fake_event) {
02906       res = p->fake_event;
02907       p->fake_event = 0;
02908    } else
02909       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02910 
02911    return dahdievent_to_analogevent(res);
02912 }

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

Definition at line 2437 of file chan_dahdi.c.

References dahdi_pvt::dialstring.

02438 {
02439    struct dahdi_pvt *p = pvt;
02440 
02441    return p->dialstring;
02442 }

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

Definition at line 2264 of file chan_dahdi.c.

References analog_lib_handles(), ast_bridged_channel(), dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, dahdi_pvt::sig_pvt, ast_channel::tech, and ast_channel::tech_pvt.

02265 {
02266    struct ast_channel *bridged = ast_bridged_channel(chan);
02267 
02268    if (bridged && bridged->tech == &dahdi_tech) {
02269       struct dahdi_pvt *p = bridged->tech_pvt;
02270 
02271       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02272          return p->sig_pvt;
02273       }
02274    }
02275    return NULL;
02276 }

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

Definition at line 2278 of file chan_dahdi.c.

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

02279 {
02280    struct dahdi_pvt *p = pvt;
02281    int dahdi_sub = analogsub_to_dahdisub(sub);
02282    return p->subs[dahdi_sub].dfd;
02283 }

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

Definition at line 9874 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by analog_ss_thread().

09875 {
09876    char c;
09877 
09878    *str = 0; /* start with empty output buffer */
09879    for (;;)
09880    {
09881       /* Wait for the first digit (up to specified ms). */
09882       c = ast_waitfordigit(chan, ms);
09883       /* if timeout, hangup or error, return as such */
09884       if (c < 1)
09885          return c;
09886       *str++ = c;
09887       *str = 0;
09888       if (strchr(term, c))
09889          return 1;
09890    }
09891 }

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

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

02086 {
02087    struct ast_frame *f = *dest;
02088    struct dahdi_pvt *p = pvt;
02089    int idx = analogsub_to_dahdisub(analog_index);
02090 
02091    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02092       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02093       (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
02094 
02095    if (f->subclass.integer == 'f') {
02096       if (f->frametype == AST_FRAME_DTMF_END) {
02097          /* Fax tone -- Handle and return NULL */
02098          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02099             /* If faxbuffers are configured, use them for the fax transmission */
02100             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02101                struct dahdi_bufferinfo bi = {
02102                   .txbufpolicy = p->faxbuf_policy,
02103                   .bufsize = p->bufsize,
02104                   .numbufs = p->faxbuf_no
02105                };
02106                int res;
02107 
02108                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02109                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02110                } else {
02111                   p->bufferoverrideinuse = 1;
02112                }
02113             }
02114             p->faxhandled = 1;
02115             if (p->dsp) {
02116                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02117                ast_dsp_set_features(p->dsp, p->dsp_features);
02118                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02119             }
02120             if (strcmp(ast->exten, "fax")) {
02121                const char *target_context = S_OR(ast->macrocontext, ast->context);
02122 
02123                /* We need to unlock 'ast' here because ast_exists_extension has the
02124                 * potential to start autoservice on the channel. Such action is prone
02125                 * to deadlock.
02126                 */
02127                ast_mutex_unlock(&p->lock);
02128                ast_channel_unlock(ast);
02129                if (ast_exists_extension(ast, target_context, "fax", 1,
02130                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02131                   ast_channel_lock(ast);
02132                   ast_mutex_lock(&p->lock);
02133                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02134                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02135                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02136                   if (ast_async_goto(ast, target_context, "fax", 1))
02137                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02138                } else {
02139                   ast_channel_lock(ast);
02140                   ast_mutex_lock(&p->lock);
02141                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02142                }
02143             } else {
02144                ast_debug(1, "Already in a fax extension, not redirecting\n");
02145             }
02146          } else {
02147             ast_debug(1, "Fax already handled\n");
02148          }
02149          dahdi_confmute(p, 0);
02150       }
02151       p->subs[idx].f.frametype = AST_FRAME_NULL;
02152       p->subs[idx].f.subclass.integer = 0;
02153       *dest = &p->subs[idx].f;
02154    }
02155 }

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

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

Referenced by analog_ss_thread().

03690 {
03691    struct dahdi_pvt *p = pvt;
03692 
03693    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03694       return;
03695 
03696    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03697       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03698       notify_message(p->mailbox, 1);
03699    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03700       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03701       notify_message(p->mailbox, 0);
03702    }
03703    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03704    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03705    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03706       ast_hangup(chan);
03707       return;
03708    }
03709 }

static void my_hangup_polarityswitch ( void *  pvt  )  [static]

Definition at line 3019 of file chan_dahdi.c.

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

03020 {
03021    struct dahdi_pvt *p = pvt;
03022 
03023    if (!p->hanguponpolarityswitch) {
03024       return;
03025    }
03026 
03027    if (p->answeronpolarityswitch) {
03028       my_set_polarity(pvt, 0);
03029    } else {
03030       my_set_polarity(pvt, 1);
03031    }
03032 }

static int my_has_voicemail ( void *  pvt  )  [static]

Definition at line 2779 of file chan_dahdi.c.

References has_voicemail().

02780 {
02781    struct dahdi_pvt *p = pvt;
02782 
02783    return has_voicemail(p);
02784 }

static int my_have_progressdetect ( void *  pvt  )  [static]

Definition at line 3711 of file chan_dahdi.c.

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

03712 {
03713    struct dahdi_pvt *p = pvt;
03714 
03715    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03716       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03717       return 1;
03718    } else {
03719       /* Don't have progress detection. */
03720       return 0;
03721    }
03722 }

static void my_increase_ss_count ( void   )  [static]

Definition at line 2444 of file chan_dahdi.c.

References ast_mutex_lock, and ast_mutex_unlock.

02445 {
02446    ast_mutex_lock(&ss_thread_lock);
02447    ss_thread_count++;
02448    ast_mutex_unlock(&ss_thread_lock);
02449 }

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

Definition at line 3084 of file chan_dahdi.c.

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

03085 {
03086    struct dahdi_pvt *p = pvt;
03087    int index;
03088    int x;
03089 
03090    index = analogsub_to_dahdisub(sub);
03091 
03092    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03093       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03094       return -1;
03095    }
03096 
03097    return x;
03098 }

static int my_is_off_hook ( void *  pvt  )  [static]

Definition at line 2914 of file chan_dahdi.c.

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

02915 {
02916    struct dahdi_pvt *p = pvt;
02917    int res;
02918    struct dahdi_params par;
02919 
02920    memset(&par, 0, sizeof(par));
02921 
02922    if (p->subs[SUB_REAL].dfd > -1)
02923       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02924    else {
02925       /* Assume not off hook on CVRS */
02926       res = 0;
02927       par.rxisoffhook = 0;
02928    }
02929    if (res) {
02930       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02931    }
02932 
02933    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02934       /* When "onhook" that means no battery on the line, and thus
02935       it is out of service..., if it's on a TDM card... If it's a channel
02936       bank, there is no telling... */
02937       return (par.rxbits > -1) || par.rxisoffhook;
02938    }
02939 
02940    return par.rxisoffhook;
02941 }

static void my_lock_private ( void *  pvt  )  [static]

Definition at line 2157 of file chan_dahdi.c.

References ast_mutex_lock, and dahdi_pvt::lock.

02158 {
02159    struct dahdi_pvt *p = pvt;
02160    ast_mutex_lock(&p->lock);
02161 }

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, read]

Definition at line 2609 of file chan_dahdi.c.

References analogsub_to_dahdisub(), and dahdi_new().

02610 {
02611    struct dahdi_pvt *p = pvt;
02612    int dsub = analogsub_to_dahdisub(sub);
02613 
02614    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02615 }

static int my_off_hook ( void *  pvt  )  [static]

Definition at line 2976 of file chan_dahdi.c.

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

02977 {
02978    struct dahdi_pvt *p = pvt;
02979    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02980 }

static int my_on_hook ( void *  pvt  )  [static]

Definition at line 3100 of file chan_dahdi.c.

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

03101 {
03102    struct dahdi_pvt *p = pvt;
03103    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03104 }

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

Definition at line 2786 of file chan_dahdi.c.

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

02787 {
02788    struct dahdi_pvt *p = pvt;
02789    int index;
02790 
02791    index = analogsub_to_dahdisub(sub);
02792 
02793    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02794 }

static int my_ring ( void *  pvt  )  [static]

Definition at line 2960 of file chan_dahdi.c.

References dahdi_ring_phone().

02961 {
02962    struct dahdi_pvt *p = pvt;
02963 
02964    return dahdi_ring_phone(p);
02965 }

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

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

01985 {
01986    struct dahdi_pvt *p = pvt;
01987 
01988    ast_debug(2, "Starting cid spill\n");
01989 
01990    if (p->cidspill) {
01991       ast_log(LOG_WARNING, "cidspill already exists??\n");
01992       ast_free(p->cidspill);
01993    }
01994 
01995    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01996       if (cwcid == 0) {
01997          p->cidlen = ast_callerid_generate(p->cidspill,
01998             caller->id.name.str,
01999             caller->id.number.str,
02000             AST_LAW(p));
02001       } else {
02002          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
02003             caller->id.name.str, caller->id.number.str);
02004          p->callwaitcas = 0;
02005          p->cidcwexpire = 0;
02006          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
02007             caller->id.name.str,
02008             caller->id.number.str,
02009             AST_LAW(p));
02010          p->cidlen += READ_SIZE * 4;
02011       }
02012       p->cidpos = 0;
02013       p->cid_suppress_expire = 0;
02014       send_callerid(p);
02015    }
02016    return 0;
02017 }

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

Definition at line 2301 of file chan_dahdi.c.

References dahdi_pvt::inalarm.

02302 {
02303    struct dahdi_pvt *p = pvt;
02304 
02305    p->inalarm = in_alarm;
02306 }

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

Definition at line 2285 of file chan_dahdi.c.

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

02286 {
02287    struct dahdi_pvt *p = pvt;
02288 
02289    /* Choose proper cadence */
02290    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02291       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02292          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02293       *cid_rings = cidrings[p->distinctivering - 1];
02294    } else {
02295       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02296          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02297       *cid_rings = p->sendcalleridafter;
02298    }
02299 }

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

Definition at line 2402 of file chan_dahdi.c.

References dahdi_pvt::callwaiting.

02403 {
02404    struct dahdi_pvt *p = pvt;
02405 
02406    p->callwaiting = callwaiting_enable;
02407 }

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

Definition at line 2386 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

02387 {
02388    struct dahdi_pvt *p = pvt;
02389    p->confirmanswer = flag;
02390 }

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

Definition at line 2308 of file chan_dahdi.c.

References dahdi_pvt::dialing.

02309 {
02310    struct dahdi_pvt *p = pvt;
02311 
02312    p->dialing = is_dialing;
02313 }

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

Definition at line 2946 of file chan_dahdi.c.

References dahdi_disable_ec(), and dahdi_enable_ec().

02947 {
02948    struct dahdi_pvt *p = pvt;
02949 
02950    if (enable)
02951       dahdi_enable_ec(p);
02952    else
02953       dahdi_disable_ec(p);
02954 
02955    return 0;
02956 }

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

Definition at line 2245 of file chan_dahdi.c.

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

02246 {
02247    struct dahdi_pvt *p = pvt;
02248    int idx = analogsub_to_dahdisub(sub);
02249 
02250    p->subs[idx].inthreeway = inthreeway;
02251 }

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

Definition at line 2233 of file chan_dahdi.c.

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

02234 {
02235    struct dahdi_pvt *p = pvt;
02236    int oldval;
02237    int idx = analogsub_to_dahdisub(sub);
02238    
02239    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02240    oldval = p->subs[idx].linear;
02241    p->subs[idx].linear = linear_mode ? 1 : 0;
02242    return oldval;
02243 }

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

Definition at line 2982 of file chan_dahdi.c.

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

02983 {
02984    struct dahdi_pvt *p = pvt;
02985    p->subs[SUB_REAL].needringing = value;
02986 }

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

Definition at line 2430 of file chan_dahdi.c.

References dahdi_pvt::owner.

02431 {
02432    struct dahdi_pvt *p = pvt;
02433 
02434    p->owner = new_owner;
02435 }

static void my_set_outgoing ( void *  pvt,
int  is_outgoing 
) [static]

Definition at line 2315 of file chan_dahdi.c.

References dahdi_pvt::outgoing.

02316 {
02317    struct dahdi_pvt *p = pvt;
02318 
02319    p->outgoing = is_outgoing;
02320 }

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

Definition at line 2988 of file chan_dahdi.c.

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

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

02989 {
02990    struct dahdi_pvt *p = pvt;
02991 
02992    if (p->channel == CHAN_PSEUDO) {
02993       return;
02994    }
02995    p->polarity = value;
02996    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02997 }

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

Definition at line 2424 of file chan_dahdi.c.

References dahdi_pvt::pulsedial.

02425 {
02426    struct dahdi_pvt *p = pvt;
02427    p->pulsedial = flag;
02428 }

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

Definition at line 2358 of file chan_dahdi.c.

References dahdi_pvt::ringt.

02359 {
02360    struct dahdi_pvt *p = pvt;
02361    p->ringt = ringt;
02362 }

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

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

02365 {
02366    struct dahdi_pvt *p = pvt;
02367 
02368    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02369       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02370       gettimeofday(&p->waitingfordt, NULL);
02371       ast_setstate(ast, AST_STATE_OFFHOOK);
02372    }
02373 }

static int my_start ( void *  pvt  )  [static]

Definition at line 3034 of file chan_dahdi.c.

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

03035 {
03036    struct dahdi_pvt *p = pvt;
03037    int x = DAHDI_START;
03038 
03039    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03040 }

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

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

01717 {
01718    struct dahdi_pvt *p = pvt;
01719    int index = SUB_REAL;
01720    p->cs = callerid_new(cid_signalling);
01721    if (!p->cs) {
01722       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01723       return -1;
01724    }
01725    bump_gains(p);
01726    dahdi_setlinear(p->subs[index].dfd, 0);
01727 
01728    return 0;
01729 }

static void my_start_polarityswitch ( void *  pvt  )  [static]

Definition at line 2999 of file chan_dahdi.c.

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

03000 {
03001    struct dahdi_pvt *p = pvt;
03002 
03003    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03004       my_set_polarity(pvt, 0);
03005    }
03006 }

static int my_stop_callwait ( void *  pvt  )  [static]

Definition at line 1937 of file chan_dahdi.c.

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

01938 {
01939    struct dahdi_pvt *p = pvt;
01940    p->callwaitingrepeat = 0;
01941    p->cidcwexpire = 0;
01942    p->cid_suppress_expire = 0;
01943 
01944    return 0;
01945 }

static int my_stop_cid_detect ( void *  pvt  )  [static]

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

01732 {
01733    struct dahdi_pvt *p = pvt;
01734    int index = SUB_REAL;
01735    if (p->cs)
01736       callerid_free(p->cs);
01737    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01738    return 0;
01739 }

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

02576 {
02577    struct dahdi_pvt *p = pvt;
02578    int da, db;
02579    int tchan;
02580    int tinthreeway;
02581 
02582    da = analogsub_to_dahdisub(a);
02583    db = analogsub_to_dahdisub(b);
02584 
02585    tchan = p->subs[da].chan;
02586    p->subs[da].chan = p->subs[db].chan;
02587    p->subs[db].chan = tchan;
02588 
02589    tinthreeway = p->subs[da].inthreeway;
02590    p->subs[da].inthreeway = p->subs[db].inthreeway;
02591    p->subs[db].inthreeway = tinthreeway;
02592 
02593    p->subs[da].owner = ast_a;
02594    p->subs[db].owner = ast_b;
02595 
02596    if (ast_a)
02597       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02598    if (ast_b)
02599       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02600 
02601    wakeup_sub(p, a);
02602    wakeup_sub(p, b);
02603 
02604    return;
02605 }

static int my_train_echocanceller ( void *  pvt  )  [static]

Definition at line 3075 of file chan_dahdi.c.

References dahdi_train_ec().

03076 {
03077    struct dahdi_pvt *p = pvt;
03078 
03079    dahdi_train_ec(p);
03080 
03081    return 0;
03082 }

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

Definition at line 2761 of file chan_dahdi.c.

References analogsub_to_dahdisub(), and unalloc_sub().

02762 {
02763    struct dahdi_pvt *p = pvt;
02764 
02765    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02766 }

static void my_unlock_private ( void *  pvt  )  [static]

Definition at line 2163 of file chan_dahdi.c.

References ast_mutex_unlock, and dahdi_pvt::lock.

02164 {
02165    struct dahdi_pvt *p = pvt;
02166    ast_mutex_unlock(&p->lock);
02167 }

static int my_wait_event ( void *  pvt  )  [static]

Definition at line 2893 of file chan_dahdi.c.

References dahdi_wait_event(), dahdi_subchannel::dfd, SUB_REAL, and dahdi_pvt::subs.

02894 {
02895    struct dahdi_pvt *p = pvt;
02896 
02897    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02898 }

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

Definition at line 2069 of file chan_dahdi.c.

References analogsub_to_dahdisub(), ast_log(), dahdi_wink(), LOG_ERROR, and SUB_REAL.

02070 {
02071    struct dahdi_pvt *p = pvt;
02072    int index = analogsub_to_dahdisub(sub);
02073    if (index != SUB_REAL) {
02074       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02075    }
02076    return dahdi_wink(p, index);
02077 }

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

Send MWI state change.

  • mailbox_full This is the mailbox associated with the FXO line that the MWI state has changed on.
  • thereornot This argument should simply be set to 1 or 0, to indicate whether there are messages waiting or not.
Returns:
nothing

This function does two things:

1) It generates an internal Asterisk event notifying any other module that cares about MWI that the state of a mailbox has changed.

2) It runs the script specified by the mwimonitornotify option to allow some custom handling of the state change.

Definition at line 3660 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, and mailbox.

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

03661 {
03662    char s[sizeof(mwimonitornotify) + 80];
03663    struct ast_event *event;
03664    char *mailbox, *context;
03665 
03666    /* Strip off @default */
03667    context = mailbox = ast_strdupa(mailbox_full);
03668    strsep(&context, "@");
03669    if (ast_strlen_zero(context))
03670       context = "default";
03671 
03672    if (!(event = ast_event_new(AST_EVENT_MWI,
03673          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03674          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03675          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03676          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03677          AST_EVENT_IE_END))) {
03678       return;
03679    }
03680 
03681    ast_event_queue_and_cache(event);
03682 
03683    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03684       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03685       ast_safe_system(s);
03686    }
03687 }

static int parse_buffers_policy ( const char *  parse,
int *  num_buffers,
int *  policy 
) [static]

Definition at line 7078 of file chan_dahdi.c.

References ast_log(), and LOG_WARNING.

Referenced by dahdi_func_write(), and process_dahdi().

07079 {
07080    int res;
07081    char policy_str[21] = "";
07082 
07083    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07084       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07085       return 1;
07086    }
07087    if (*num_buffers < 0) {
07088       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07089       return -1;
07090    }
07091    if (!strcasecmp(policy_str, "full")) {
07092       *policy = DAHDI_POLICY_WHEN_FULL;
07093    } else if (!strcasecmp(policy_str, "immediate")) {
07094       *policy = DAHDI_POLICY_IMMEDIATE;
07095 #if defined(HAVE_DAHDI_HALF_FULL)
07096    } else if (!strcasecmp(policy_str, "half")) {
07097       *policy = DAHDI_POLICY_HALF_FULL;
07098 #endif
07099    } else {
07100       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07101       return -1;
07102    }
07103 
07104    return 0;
07105 }

static char* parse_spanchan ( char *  chanstr,
char **  subdir 
) [static]

Definition at line 16999 of file chan_dahdi.c.

References string_replace().

Referenced by build_channels().

17000 {
17001    char *p;
17002 
17003    if ((p = strrchr(chanstr, '!')) == NULL) {
17004       *subdir = NULL;
17005       return chanstr;
17006    }
17007    *p++ = '\0';
17008    string_replace(chanstr, '!', '/');
17009    *subdir = chanstr;
17010    return p;
17011 }

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

Definition at line 17142 of file chan_dahdi.c.

References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_callerid_split(), ast_cc_config_params_destroy(), ast_cc_is_config_param(), ast_cc_set_param(), ast_cdr_amaflags2int(), ast_copy_string(), ast_get_group(), ast_jb_read_conf(), ast_log(), AST_MAX_EXTENSION, ast_strdupa, ast_strlen_zero(), ast_true(), ast_variable_new(), ast_variables_destroy(), ast_verb, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, build_channels(), dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::callgroup, dahdi_pvt::callprogress, CALLPROGRESS_FAX, CALLPROGRESS_FAX_INCOMING, CALLPROGRESS_FAX_OUTGOING, CALLPROGRESS_PROGRESS, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_pvt::cc_params, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_rxgain, CID_SIG_BELL, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, CID_START_POLARITY_IN, CID_START_RING, dahdi_pvt::cid_tag, dahdi_pvt::context, ringContextData::contextData, dahdi_chan_conf_default(), DAHDI_CHAN_MAPPING_LOGICAL, DAHDI_CHAN_MAPPING_PHYSICAL, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_NONE, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pvt::dahditrcallerid, dahdi_pvt::destroy, dahdi_pvt::drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echotraining, errno, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_chan_conf::ignore_failed_channels, dahdi_pvt::immediate, dahdi_chan_conf::is_sig_auto, dahdi_pvt::language, ast_variable::lineno, LINKSET_FLAG_EXPLICITACM, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::manages_span_alarms, mkintf(), dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, ast_variable::name, dahdi_pvt::next, ast_variable::next, NUM_CADENCE_MAX, dahdi_pvt::outsigmod, dahdi_pvt::parkinglot, parse_buffers_policy(), dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_echocancel(), dahdi_pvt::pulse, dahdi_pvt::radio, distRingData::range, READ_SIZE, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, SIG_PRI_AOC_GRANT_D, SIG_PRI_AOC_GRANT_E, SIG_PRI_AOC_GRANT_S, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, SIG_SS7, dahdi_pvt::silencethreshold, dahdi_chan_conf::smdi_port, dahdi_pvt::span, SS7_NAI_DYNAMIC, dahdi_pvt::stripmsd, dahdi_pvt::threewaycalling, timer, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txdrc, dahdi_pvt::txgain, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, dahdi_pvt::usefaxbuffers, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

Referenced by setup_dahdi_int().

17143 {
17144    struct dahdi_pvt *tmp;
17145    int y;
17146    int found_pseudo = 0;
17147    struct ast_variable *dahdichan = NULL;
17148 
17149    for (; v; v = v->next) {
17150       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17151          continue;
17152 
17153       /* Create the interface list */
17154       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17155          if (options & PROC_DAHDI_OPT_NOCHAN) {
17156             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17157             continue;
17158          }
17159          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17160             if (confp->ignore_failed_channels) {
17161                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17162                continue;
17163             } else {
17164                return -1;
17165             }
17166          }
17167          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
17168       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17169          confp->ignore_failed_channels = ast_true(v->value);
17170       } else if (!strcasecmp(v->name, "buffers")) {
17171          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17172             ast_log(LOG_WARNING, "Using default buffer policy.\n");
17173             confp->chan.buf_no = numbufs;
17174             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17175          }
17176       } else if (!strcasecmp(v->name, "faxbuffers")) {
17177          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17178             confp->chan.usefaxbuffers = 1;
17179          }
17180       } else if (!strcasecmp(v->name, "dahdichan")) {
17181          /* Only process the last dahdichan value. */
17182          dahdichan = v;
17183       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17184          usedistinctiveringdetection = ast_true(v->value);
17185       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17186          distinctiveringaftercid = ast_true(v->value);
17187       } else if (!strcasecmp(v->name, "dring1context")) {
17188          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17189       } else if (!strcasecmp(v->name, "dring2context")) {
17190          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17191       } else if (!strcasecmp(v->name, "dring3context")) {
17192          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17193       } else if (!strcasecmp(v->name, "dring1range")) {
17194          confp->chan.drings.ringnum[0].range = atoi(v->value);
17195       } else if (!strcasecmp(v->name, "dring2range")) {
17196          confp->chan.drings.ringnum[1].range = atoi(v->value);
17197       } else if (!strcasecmp(v->name, "dring3range")) {
17198          confp->chan.drings.ringnum[2].range = atoi(v->value);
17199       } else if (!strcasecmp(v->name, "dring1")) {
17200          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]);
17201       } else if (!strcasecmp(v->name, "dring2")) {
17202          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]);
17203       } else if (!strcasecmp(v->name, "dring3")) {
17204          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]);
17205       } else if (!strcasecmp(v->name, "usecallerid")) {
17206          confp->chan.use_callerid = ast_true(v->value);
17207       } else if (!strcasecmp(v->name, "cidsignalling")) {
17208          if (!strcasecmp(v->value, "bell"))
17209             confp->chan.cid_signalling = CID_SIG_BELL;
17210          else if (!strcasecmp(v->value, "v23"))
17211             confp->chan.cid_signalling = CID_SIG_V23;
17212          else if (!strcasecmp(v->value, "dtmf"))
17213             confp->chan.cid_signalling = CID_SIG_DTMF;
17214          else if (!strcasecmp(v->value, "smdi"))
17215             confp->chan.cid_signalling = CID_SIG_SMDI;
17216          else if (!strcasecmp(v->value, "v23_jp"))
17217             confp->chan.cid_signalling = CID_SIG_V23_JP;
17218          else if (ast_true(v->value))
17219             confp->chan.cid_signalling = CID_SIG_BELL;
17220       } else if (!strcasecmp(v->name, "cidstart")) {
17221          if (!strcasecmp(v->value, "ring"))
17222             confp->chan.cid_start = CID_START_RING;
17223          else if (!strcasecmp(v->value, "polarity_in"))
17224             confp->chan.cid_start = CID_START_POLARITY_IN;
17225          else if (!strcasecmp(v->value, "polarity"))
17226             confp->chan.cid_start = CID_START_POLARITY;
17227          else if (!strcasecmp(v->value, "dtmf"))
17228             confp->chan.cid_start = CID_START_DTMF_NOALERT;
17229          else if (ast_true(v->value))
17230             confp->chan.cid_start = CID_START_RING;
17231       } else if (!strcasecmp(v->name, "threewaycalling")) {
17232          confp->chan.threewaycalling = ast_true(v->value);
17233       } else if (!strcasecmp(v->name, "cancallforward")) {
17234          confp->chan.cancallforward = ast_true(v->value);
17235       } else if (!strcasecmp(v->name, "relaxdtmf")) {
17236          if (ast_true(v->value))
17237             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17238          else
17239             confp->chan.dtmfrelax = 0;
17240       } else if (!strcasecmp(v->name, "mailbox")) {
17241          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17242       } else if (!strcasecmp(v->name, "hasvoicemail")) {
17243          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17244             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17245          }
17246       } else if (!strcasecmp(v->name, "adsi")) {
17247          confp->chan.adsi = ast_true(v->value);
17248       } else if (!strcasecmp(v->name, "usesmdi")) {
17249          confp->chan.use_smdi = ast_true(v->value);
17250       } else if (!strcasecmp(v->name, "smdiport")) {
17251          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17252       } else if (!strcasecmp(v->name, "transfer")) {
17253          confp->chan.transfer = ast_true(v->value);
17254       } else if (!strcasecmp(v->name, "canpark")) {
17255          confp->chan.canpark = ast_true(v->value);
17256       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17257          confp->chan.echocanbridged = ast_true(v->value);
17258       } else if (!strcasecmp(v->name, "busydetect")) {
17259          confp->chan.busydetect = ast_true(v->value);
17260       } else if (!strcasecmp(v->name, "busycount")) {
17261          confp->chan.busycount = atoi(v->value);
17262       } else if (!strcasecmp(v->name, "silencethreshold")) {
17263          confp->chan.silencethreshold = atoi(v->value);
17264       } else if (!strcasecmp(v->name, "busycompare")) {
17265          confp->chan.busycompare = ast_true(v->value);
17266       } else if (!strcasecmp(v->name, "busypattern")) {
17267          if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
17268             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17269          }
17270          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
17271          if (count == 1)
17272             confp->chan.busyquietlength = 0;
17273          else if (count < 1)
17274             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
17275       } else if (!strcasecmp(v->name, "busyfuzziness")) {
17276          confp->chan.busyfuzziness = atoi(v->value);
17277       } else if (!strcasecmp(v->name, "callprogress")) {
17278          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17279          if (ast_true(v->value))
17280             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17281       } else if (!strcasecmp(v->name, "waitfordialtone")) {
17282          confp->chan.waitfordialtone = atoi(v->value);
17283       } else if (!strcasecmp(v->name, "faxdetect")) {
17284          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17285          if (!strcasecmp(v->value, "incoming")) {
17286             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17287          } else if (!strcasecmp(v->value, "outgoing")) {
17288             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17289          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17290             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17291       } else if (!strcasecmp(v->name, "echocancel")) {
17292          process_echocancel(confp, v->value, v->lineno);
17293       } else if (!strcasecmp(v->name, "echotraining")) {
17294          if (sscanf(v->value, "%30d", &y) == 1) {
17295             if ((y < 10) || (y > 4000)) {
17296                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17297             } else {
17298                confp->chan.echotraining = y;
17299             }
17300          } else if (ast_true(v->value)) {
17301             confp->chan.echotraining = 400;
17302          } else
17303             confp->chan.echotraining = 0;
17304       } else if (!strcasecmp(v->name, "hidecallerid")) {
17305          confp->chan.hidecallerid = ast_true(v->value);
17306       } else if (!strcasecmp(v->name, "hidecalleridname")) {
17307          confp->chan.hidecalleridname = ast_true(v->value);
17308       } else if (!strcasecmp(v->name, "pulsedial")) {
17309          confp->chan.pulse = ast_true(v->value);
17310       } else if (!strcasecmp(v->name, "callreturn")) {
17311          confp->chan.callreturn = ast_true(v->value);
17312       } else if (!strcasecmp(v->name, "callwaiting")) {
17313          confp->chan.callwaiting = ast_true(v->value);
17314       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17315          confp->chan.callwaitingcallerid = ast_true(v->value);
17316       } else if (!strcasecmp(v->name, "context")) {
17317          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17318       } else if (!strcasecmp(v->name, "language")) {
17319          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17320       } else if (!strcasecmp(v->name, "progzone")) {
17321          ast_copy_string(progzone, v->value, sizeof(progzone));
17322       } else if (!strcasecmp(v->name, "mohinterpret")
17323          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17324          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17325       } else if (!strcasecmp(v->name, "mohsuggest")) {
17326          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17327       } else if (!strcasecmp(v->name, "parkinglot")) {
17328          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17329       } else if (!strcasecmp(v->name, "stripmsd")) {
17330          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17331          confp->chan.stripmsd = atoi(v->value);
17332       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17333          numbufs = atoi(v->value);
17334       } else if (!strcasecmp(v->name, "group")) {
17335          confp->chan.group = ast_get_group(v->value);
17336       } else if (!strcasecmp(v->name, "callgroup")) {
17337          if (!strcasecmp(v->value, "none"))
17338             confp->chan.callgroup = 0;
17339          else
17340             confp->chan.callgroup = ast_get_group(v->value);
17341       } else if (!strcasecmp(v->name, "pickupgroup")) {
17342          if (!strcasecmp(v->value, "none"))
17343             confp->chan.pickupgroup = 0;
17344          else
17345             confp->chan.pickupgroup = ast_get_group(v->value);
17346       } else if (!strcasecmp(v->name, "setvar")) {
17347          char *varname = ast_strdupa(v->value), *varval = NULL;
17348          struct ast_variable *tmpvar;
17349          if (varname && (varval = strchr(varname, '='))) {
17350             *varval++ = '\0';
17351             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17352                tmpvar->next = confp->chan.vars;
17353                confp->chan.vars = tmpvar;
17354             }
17355          }
17356       } else if (!strcasecmp(v->name, "immediate")) {
17357          confp->chan.immediate = ast_true(v->value);
17358       } else if (!strcasecmp(v->name, "transfertobusy")) {
17359          confp->chan.transfertobusy = ast_true(v->value);
17360       } else if (!strcasecmp(v->name, "mwimonitor")) {
17361          confp->chan.mwimonitor_neon = 0;
17362          confp->chan.mwimonitor_fsk = 0;
17363          confp->chan.mwimonitor_rpas = 0;
17364          if (strcasestr(v->value, "fsk")) {
17365             confp->chan.mwimonitor_fsk = 1;
17366          }
17367          if (strcasestr(v->value, "rpas")) {
17368             confp->chan.mwimonitor_rpas = 1;
17369          }
17370          if (strcasestr(v->value, "neon")) {
17371             confp->chan.mwimonitor_neon = 1;
17372          }
17373          /* If set to true or yes, assume that simple fsk is desired */
17374          if (ast_true(v->value)) {
17375             confp->chan.mwimonitor_fsk = 1;
17376          }
17377       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17378          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17379             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17380          }
17381       } else if (!strcasecmp(v->name, "rxgain")) {
17382          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17383             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17384          }
17385       } else if (!strcasecmp(v->name, "txgain")) {
17386          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17387             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17388          }
17389       } else if (!strcasecmp(v->name, "txdrc")) {
17390          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17391             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17392          }
17393       } else if (!strcasecmp(v->name, "rxdrc")) {
17394          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17395             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17396          }
17397       } else if (!strcasecmp(v->name, "tonezone")) {
17398          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17399             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17400          }
17401       } else if (!strcasecmp(v->name, "callerid")) {
17402          if (!strcasecmp(v->value, "asreceived")) {
17403             confp->chan.cid_num[0] = '\0';
17404             confp->chan.cid_name[0] = '\0';
17405          } else {
17406             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17407          }
17408       } else if (!strcasecmp(v->name, "fullname")) {
17409          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17410       } else if (!strcasecmp(v->name, "cid_number")) {
17411          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17412       } else if (!strcasecmp(v->name, "cid_tag")) {
17413          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17414       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17415          confp->chan.dahditrcallerid = ast_true(v->value);
17416       } else if (!strcasecmp(v->name, "restrictcid")) {
17417          confp->chan.restrictcid = ast_true(v->value);
17418       } else if (!strcasecmp(v->name, "usecallingpres")) {
17419          confp->chan.use_callingpres = ast_true(v->value);
17420       } else if (!strcasecmp(v->name, "accountcode")) {
17421          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17422       } else if (!strcasecmp(v->name, "amaflags")) {
17423          y = ast_cdr_amaflags2int(v->value);
17424          if (y < 0)
17425             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17426          else
17427             confp->chan.amaflags = y;
17428       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17429          confp->chan.polarityonanswerdelay = atoi(v->value);
17430       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17431          confp->chan.answeronpolarityswitch = ast_true(v->value);
17432       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17433          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17434       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17435          confp->chan.sendcalleridafter = atoi(v->value);
17436       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17437          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17438       } else if (ast_cc_is_config_param(v->name)) {
17439          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17440       } else if (!strcasecmp(v->name, "mwisendtype")) {
17441 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17442          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17443             mwisend_rpas = 1;
17444          } else {
17445             mwisend_rpas = 0;
17446          }
17447 #else
17448          /* Default is fsk, to turn it off you must specify nofsk */
17449          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17450          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17451             confp->chan.mwisend_fsk = 0;
17452          } else {             /* Default FSK */
17453             confp->chan.mwisend_fsk = 1;
17454          }
17455          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17456             confp->chan.mwisend_rpas = 1;
17457          } else {
17458             confp->chan.mwisend_rpas = 0;
17459          }
17460          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17461             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17462          }
17463          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17464             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17465          }
17466          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17467             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17468          }
17469 #endif
17470       } else if (reload != 1) {
17471           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17472             int orig_radio = confp->chan.radio;
17473             int orig_outsigmod = confp->chan.outsigmod;
17474             int orig_auto = confp->is_sig_auto;
17475 
17476             confp->chan.radio = 0;
17477             confp->chan.outsigmod = -1;
17478             confp->is_sig_auto = 0;
17479             if (!strcasecmp(v->value, "em")) {
17480                confp->chan.sig = SIG_EM;
17481             } else if (!strcasecmp(v->value, "em_e1")) {
17482                confp->chan.sig = SIG_EM_E1;
17483             } else if (!strcasecmp(v->value, "em_w")) {
17484                confp->chan.sig = SIG_EMWINK;
17485             } else if (!strcasecmp(v->value, "fxs_ls")) {
17486                confp->chan.sig = SIG_FXSLS;
17487             } else if (!strcasecmp(v->value, "fxs_gs")) {
17488                confp->chan.sig = SIG_FXSGS;
17489             } else if (!strcasecmp(v->value, "fxs_ks")) {
17490                confp->chan.sig = SIG_FXSKS;
17491             } else if (!strcasecmp(v->value, "fxo_ls")) {
17492                confp->chan.sig = SIG_FXOLS;
17493             } else if (!strcasecmp(v->value, "fxo_gs")) {
17494                confp->chan.sig = SIG_FXOGS;
17495             } else if (!strcasecmp(v->value, "fxo_ks")) {
17496                confp->chan.sig = SIG_FXOKS;
17497             } else if (!strcasecmp(v->value, "fxs_rx")) {
17498                confp->chan.sig = SIG_FXSKS;
17499                confp->chan.radio = 1;
17500             } else if (!strcasecmp(v->value, "fxo_rx")) {
17501                confp->chan.sig = SIG_FXOLS;
17502                confp->chan.radio = 1;
17503             } else if (!strcasecmp(v->value, "fxs_tx")) {
17504                confp->chan.sig = SIG_FXSLS;
17505                confp->chan.radio = 1;
17506             } else if (!strcasecmp(v->value, "fxo_tx")) {
17507                confp->chan.sig = SIG_FXOGS;
17508                confp->chan.radio = 1;
17509             } else if (!strcasecmp(v->value, "em_rx")) {
17510                confp->chan.sig = SIG_EM;
17511                confp->chan.radio = 1;
17512             } else if (!strcasecmp(v->value, "em_tx")) {
17513                confp->chan.sig = SIG_EM;
17514                confp->chan.radio = 1;
17515             } else if (!strcasecmp(v->value, "em_rxtx")) {
17516                confp->chan.sig = SIG_EM;
17517                confp->chan.radio = 2;
17518             } else if (!strcasecmp(v->value, "em_txrx")) {
17519                confp->chan.sig = SIG_EM;
17520                confp->chan.radio = 2;
17521             } else if (!strcasecmp(v->value, "sf")) {
17522                confp->chan.sig = SIG_SF;
17523             } else if (!strcasecmp(v->value, "sf_w")) {
17524                confp->chan.sig = SIG_SFWINK;
17525             } else if (!strcasecmp(v->value, "sf_featd")) {
17526                confp->chan.sig = SIG_FEATD;
17527             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17528                confp->chan.sig = SIG_FEATDMF;
17529             } else if (!strcasecmp(v->value, "sf_featb")) {
17530                confp->chan.sig = SIG_SF_FEATB;
17531             } else if (!strcasecmp(v->value, "sf")) {
17532                confp->chan.sig = SIG_SF;
17533             } else if (!strcasecmp(v->value, "sf_rx")) {
17534                confp->chan.sig = SIG_SF;
17535                confp->chan.radio = 1;
17536             } else if (!strcasecmp(v->value, "sf_tx")) {
17537                confp->chan.sig = SIG_SF;
17538                confp->chan.radio = 1;
17539             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17540                confp->chan.sig = SIG_SF;
17541                confp->chan.radio = 2;
17542             } else if (!strcasecmp(v->value, "sf_txrx")) {
17543                confp->chan.sig = SIG_SF;
17544                confp->chan.radio = 2;
17545             } else if (!strcasecmp(v->value, "featd")) {
17546                confp->chan.sig = SIG_FEATD;
17547             } else if (!strcasecmp(v->value, "featdmf")) {
17548                confp->chan.sig = SIG_FEATDMF;
17549             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17550                confp->chan.sig = SIG_FEATDMF_TA;
17551             } else if (!strcasecmp(v->value, "e911")) {
17552                confp->chan.sig = SIG_E911;
17553             } else if (!strcasecmp(v->value, "fgccama")) {
17554                confp->chan.sig = SIG_FGC_CAMA;
17555             } else if (!strcasecmp(v->value, "fgccamamf")) {
17556                confp->chan.sig = SIG_FGC_CAMAMF;
17557             } else if (!strcasecmp(v->value, "featb")) {
17558                confp->chan.sig = SIG_FEATB;
17559 #ifdef HAVE_PRI
17560             } else if (!strcasecmp(v->value, "pri_net")) {
17561                confp->chan.sig = SIG_PRI;
17562                confp->pri.pri.nodetype = PRI_NETWORK;
17563             } else if (!strcasecmp(v->value, "pri_cpe")) {
17564                confp->chan.sig = SIG_PRI;
17565                confp->pri.pri.nodetype = PRI_CPE;
17566             } else if (!strcasecmp(v->value, "bri_cpe")) {
17567                confp->chan.sig = SIG_BRI;
17568                confp->pri.pri.nodetype = PRI_CPE;
17569             } else if (!strcasecmp(v->value, "bri_net")) {
17570                confp->chan.sig = SIG_BRI;
17571                confp->pri.pri.nodetype = PRI_NETWORK;
17572             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17573                confp->chan.sig = SIG_BRI_PTMP;
17574                confp->pri.pri.nodetype = PRI_CPE;
17575             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17576 #if defined(HAVE_PRI_CALL_HOLD)
17577                confp->chan.sig = SIG_BRI_PTMP;
17578                confp->pri.pri.nodetype = PRI_NETWORK;
17579 #else
17580                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17581 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
17582 #endif
17583 #if defined(HAVE_SS7)
17584             } else if (!strcasecmp(v->value, "ss7")) {
17585                confp->chan.sig = SIG_SS7;
17586 #endif   /* defined(HAVE_SS7) */
17587 #ifdef HAVE_OPENR2
17588             } else if (!strcasecmp(v->value, "mfcr2")) {
17589                confp->chan.sig = SIG_MFCR2;
17590 #endif
17591             } else if (!strcasecmp(v->value, "auto")) {
17592                confp->is_sig_auto = 1;
17593             } else {
17594                confp->chan.outsigmod = orig_outsigmod;
17595                confp->chan.radio = orig_radio;
17596                confp->is_sig_auto = orig_auto;
17597                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17598             }
17599           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17600             if (!strcasecmp(v->value, "em")) {
17601                confp->chan.outsigmod = SIG_EM;
17602             } else if (!strcasecmp(v->value, "em_e1")) {
17603                confp->chan.outsigmod = SIG_EM_E1;
17604             } else if (!strcasecmp(v->value, "em_w")) {
17605                confp->chan.outsigmod = SIG_EMWINK;
17606             } else if (!strcasecmp(v->value, "sf")) {
17607                confp->chan.outsigmod = SIG_SF;
17608             } else if (!strcasecmp(v->value, "sf_w")) {
17609                confp->chan.outsigmod = SIG_SFWINK;
17610             } else if (!strcasecmp(v->value, "sf_featd")) {
17611                confp->chan.outsigmod = SIG_FEATD;
17612             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17613                confp->chan.outsigmod = SIG_FEATDMF;
17614             } else if (!strcasecmp(v->value, "sf_featb")) {
17615                confp->chan.outsigmod = SIG_SF_FEATB;
17616             } else if (!strcasecmp(v->value, "sf")) {
17617                confp->chan.outsigmod = SIG_SF;
17618             } else if (!strcasecmp(v->value, "featd")) {
17619                confp->chan.outsigmod = SIG_FEATD;
17620             } else if (!strcasecmp(v->value, "featdmf")) {
17621                confp->chan.outsigmod = SIG_FEATDMF;
17622             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17623                confp->chan.outsigmod = SIG_FEATDMF_TA;
17624             } else if (!strcasecmp(v->value, "e911")) {
17625                confp->chan.outsigmod = SIG_E911;
17626             } else if (!strcasecmp(v->value, "fgccama")) {
17627                confp->chan.outsigmod = SIG_FGC_CAMA;
17628             } else if (!strcasecmp(v->value, "fgccamamf")) {
17629                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17630             } else if (!strcasecmp(v->value, "featb")) {
17631                confp->chan.outsigmod = SIG_FEATB;
17632             } else {
17633                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17634             }
17635 #ifdef HAVE_PRI
17636          } else if (!strcasecmp(v->name, "pridialplan")) {
17637             if (!strcasecmp(v->value, "national")) {
17638                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17639             } else if (!strcasecmp(v->value, "unknown")) {
17640                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17641             } else if (!strcasecmp(v->value, "private")) {
17642                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17643             } else if (!strcasecmp(v->value, "international")) {
17644                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17645             } else if (!strcasecmp(v->value, "local")) {
17646                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17647             } else if (!strcasecmp(v->value, "dynamic")) {
17648                confp->pri.pri.dialplan = -1;
17649             } else if (!strcasecmp(v->value, "redundant")) {
17650                confp->pri.pri.dialplan = -2;
17651             } else {
17652                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17653             }
17654          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17655             if (!strcasecmp(v->value, "national")) {
17656                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17657             } else if (!strcasecmp(v->value, "unknown")) {
17658                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17659             } else if (!strcasecmp(v->value, "private")) {
17660                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17661             } else if (!strcasecmp(v->value, "international")) {
17662                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17663             } else if (!strcasecmp(v->value, "local")) {
17664                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17665             } else if (!strcasecmp(v->value, "dynamic")) {
17666                confp->pri.pri.localdialplan = -1;
17667             } else if (!strcasecmp(v->value, "redundant")) {
17668                confp->pri.pri.localdialplan = -2;
17669             } else {
17670                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17671             }
17672          } else if (!strcasecmp(v->name, "switchtype")) {
17673             if (!strcasecmp(v->value, "national"))
17674                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17675             else if (!strcasecmp(v->value, "ni1"))
17676                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17677             else if (!strcasecmp(v->value, "dms100"))
17678                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17679             else if (!strcasecmp(v->value, "4ess"))
17680                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17681             else if (!strcasecmp(v->value, "5ess"))
17682                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17683             else if (!strcasecmp(v->value, "euroisdn"))
17684                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17685             else if (!strcasecmp(v->value, "qsig"))
17686                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17687             else {
17688                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17689                return -1;
17690             }
17691          } else if (!strcasecmp(v->name, "msn")) {
17692             ast_copy_string(confp->pri.pri.msn_list, v->value,
17693                sizeof(confp->pri.pri.msn_list));
17694          } else if (!strcasecmp(v->name, "nsf")) {
17695             if (!strcasecmp(v->value, "sdn"))
17696                confp->pri.pri.nsf = PRI_NSF_SDN;
17697             else if (!strcasecmp(v->value, "megacom"))
17698                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17699             else if (!strcasecmp(v->value, "tollfreemegacom"))
17700                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17701             else if (!strcasecmp(v->value, "accunet"))
17702                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17703             else if (!strcasecmp(v->value, "none"))
17704                confp->pri.pri.nsf = PRI_NSF_NONE;
17705             else {
17706                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17707                confp->pri.pri.nsf = PRI_NSF_NONE;
17708             }
17709          } else if (!strcasecmp(v->name, "priindication")) {
17710             if (!strcasecmp(v->value, "outofband"))
17711                confp->chan.priindication_oob = 1;
17712             else if (!strcasecmp(v->value, "inband"))
17713                confp->chan.priindication_oob = 0;
17714             else
17715                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17716                   v->value, v->lineno);
17717          } else if (!strcasecmp(v->name, "priexclusive")) {
17718             confp->chan.priexclusive = ast_true(v->value);
17719          } else if (!strcasecmp(v->name, "internationalprefix")) {
17720             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17721          } else if (!strcasecmp(v->name, "nationalprefix")) {
17722             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17723          } else if (!strcasecmp(v->name, "localprefix")) {
17724             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17725          } else if (!strcasecmp(v->name, "privateprefix")) {
17726             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17727          } else if (!strcasecmp(v->name, "unknownprefix")) {
17728             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17729          } else if (!strcasecmp(v->name, "resetinterval")) {
17730             if (!strcasecmp(v->value, "never"))
17731                confp->pri.pri.resetinterval = -1;
17732             else if (atoi(v->value) >= 60)
17733                confp->pri.pri.resetinterval = atoi(v->value);
17734             else
17735                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17736                   v->value, v->lineno);
17737          } else if (!strcasecmp(v->name, "minunused")) {
17738             confp->pri.pri.minunused = atoi(v->value);
17739          } else if (!strcasecmp(v->name, "minidle")) {
17740             confp->pri.pri.minidle = atoi(v->value);
17741          } else if (!strcasecmp(v->name, "idleext")) {
17742             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17743          } else if (!strcasecmp(v->name, "idledial")) {
17744             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17745          } else if (!strcasecmp(v->name, "overlapdial")) {
17746             if (ast_true(v->value)) {
17747                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17748             } else if (!strcasecmp(v->value, "incoming")) {
17749                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17750             } else if (!strcasecmp(v->value, "outgoing")) {
17751                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17752             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17753                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17754             } else {
17755                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17756             }
17757 #ifdef HAVE_PRI_PROG_W_CAUSE
17758          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17759             if (!strcasecmp(v->value, "logical")) {
17760                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17761             } else if (!strcasecmp(v->value, "physical")) {
17762                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17763             } else {
17764                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17765             }
17766 #endif
17767          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17768             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17769 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17770          } else if (!strcasecmp(v->name, "service_message_support")) {
17771             /* assuming switchtype for this channel group has been configured already */
17772             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17773                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17774                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17775                confp->pri.pri.enable_service_message_support = 1;
17776             } else {
17777                confp->pri.pri.enable_service_message_support = 0;
17778             }
17779 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17780 #ifdef HAVE_PRI_INBANDDISCONNECT
17781          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17782             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17783 #endif
17784          } else if (!strcasecmp(v->name, "pritimer")) {
17785 #ifdef PRI_GETSET_TIMERS
17786             char tmp[20];
17787             char *timerc;
17788             char *c;
17789             int timer;
17790             int timeridx;
17791 
17792             ast_copy_string(tmp, v->value, sizeof(tmp));
17793             c = tmp;
17794             timerc = strsep(&c, ",");
17795             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17796                timeridx = pri_timer2idx(timerc);
17797                timer = atoi(c);
17798                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17799                   ast_log(LOG_WARNING,
17800                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17801                      v->lineno);
17802                } else if (!timer) {
17803                   ast_log(LOG_WARNING,
17804                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17805                      c, timerc, v->lineno);
17806                } else {
17807                   confp->pri.pri.pritimers[timeridx] = timer;
17808                }
17809             } else {
17810                ast_log(LOG_WARNING,
17811                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17812                   v->value, v->lineno);
17813             }
17814 #endif /* PRI_GETSET_TIMERS */
17815          } else if (!strcasecmp(v->name, "facilityenable")) {
17816             confp->pri.pri.facilityenable = ast_true(v->value);
17817 #if defined(HAVE_PRI_AOC_EVENTS)
17818          } else if (!strcasecmp(v->name, "aoc_enable")) {
17819             confp->pri.pri.aoc_passthrough_flag = 0;
17820             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17821                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17822             }
17823             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17824                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17825             }
17826             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17827                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17828             }
17829          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17830             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17831 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17832 #if defined(HAVE_PRI_CALL_HOLD)
17833          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17834             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17835 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17836 #if defined(HAVE_PRI_CCSS)
17837          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17838             if (!strcasecmp(v->value, "global")) {
17839                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17840             } else if (!strcasecmp(v->value, "specific")) {
17841                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17842             } else {
17843                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17844             }
17845          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17846             if (!strcasecmp(v->value, "release")) {
17847                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17848             } else if (!strcasecmp(v->value, "retain")) {
17849                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17850             } else if (!strcasecmp(v->value, "do_not_care")) {
17851                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17852             } else {
17853                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17854             }
17855          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17856             if (!strcasecmp(v->value, "release")) {
17857                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17858             } else if (!strcasecmp(v->value, "retain")) {
17859                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17860             } else {
17861                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17862             }
17863 #endif   /* defined(HAVE_PRI_CCSS) */
17864 #if defined(HAVE_PRI_CALL_WAITING)
17865          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17866             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17867             if (confp->pri.pri.max_call_waiting_calls < 0) {
17868                /* Negative values are not allowed. */
17869                confp->pri.pri.max_call_waiting_calls = 0;
17870             }
17871          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17872             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17873 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17874 #if defined(HAVE_PRI_MWI)
17875          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17876             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17877                sizeof(confp->pri.pri.mwi_mailboxes));
17878 #endif   /* defined(HAVE_PRI_MWI) */
17879          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17880             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17881          } else if (!strcasecmp(v->name, "inband_on_setup_ack")) {
17882             confp->pri.pri.inband_on_setup_ack = ast_true(v->value);
17883          } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
17884             confp->pri.pri.inband_on_proceeding = ast_true(v->value);
17885          } else if (!strcasecmp(v->name, "layer1_presence")) {
17886             if (!strcasecmp(v->value, "required")) {
17887                confp->pri.pri.layer1_ignored = 0;
17888             } else if (!strcasecmp(v->value, "ignore")) {
17889                confp->pri.pri.layer1_ignored = 1;
17890             } else {
17891                /* Default */
17892                confp->pri.pri.layer1_ignored = 0;
17893             }
17894 #if defined(HAVE_PRI_L2_PERSISTENCE)
17895          } else if (!strcasecmp(v->name, "layer2_persistence")) {
17896             if (!strcasecmp(v->value, "keep_up")) {
17897                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17898             } else if (!strcasecmp(v->value, "leave_down")) {
17899                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17900             } else {
17901                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17902             }
17903 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
17904 #endif /* HAVE_PRI */
17905 #if defined(HAVE_SS7)
17906          } else if (!strcasecmp(v->name, "ss7type")) {
17907             if (!strcasecmp(v->value, "itu")) {
17908                cur_ss7type = SS7_ITU;
17909             } else if (!strcasecmp(v->value, "ansi")) {
17910                cur_ss7type = SS7_ANSI;
17911             } else
17912                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17913          } else if (!strcasecmp(v->name, "linkset")) {
17914             cur_linkset = atoi(v->value);
17915          } else if (!strcasecmp(v->name, "pointcode")) {
17916             cur_pointcode = parse_pointcode(v->value);
17917          } else if (!strcasecmp(v->name, "adjpointcode")) {
17918             cur_adjpointcode = parse_pointcode(v->value);
17919          } else if (!strcasecmp(v->name, "defaultdpc")) {
17920             cur_defaultdpc = parse_pointcode(v->value);
17921          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17922             cur_cicbeginswith = atoi(v->value);
17923          } else if (!strcasecmp(v->name, "networkindicator")) {
17924             if (!strcasecmp(v->value, "national"))
17925                cur_networkindicator = SS7_NI_NAT;
17926             else if (!strcasecmp(v->value, "national_spare"))
17927                cur_networkindicator = SS7_NI_NAT_SPARE;
17928             else if (!strcasecmp(v->value, "international"))
17929                cur_networkindicator = SS7_NI_INT;
17930             else if (!strcasecmp(v->value, "international_spare"))
17931                cur_networkindicator = SS7_NI_INT_SPARE;
17932             else
17933                cur_networkindicator = -1;
17934          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17935             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17936          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17937             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17938          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17939             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17940          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17941             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17942          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17943             if (!strcasecmp(v->value, "national")) {
17944                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17945             } else if (!strcasecmp(v->value, "international")) {
17946                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17947             } else if (!strcasecmp(v->value, "subscriber")) {
17948                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17949             } else if (!strcasecmp(v->value, "unknown")) {
17950                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17951             } else if (!strcasecmp(v->value, "dynamic")) {
17952                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17953             } else {
17954                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17955             }
17956          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17957             if (!strcasecmp(v->value, "national")) {
17958                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17959             } else if (!strcasecmp(v->value, "international")) {
17960                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17961             } else if (!strcasecmp(v->value, "subscriber")) {
17962                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17963             } else if (!strcasecmp(v->value, "unknown")) {
17964                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17965             } else if (!strcasecmp(v->value, "dynamic")) {
17966                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17967             } else {
17968                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17969             }
17970          } else if (!strcasecmp(v->name, "sigchan")) {
17971             int sigchan, res;
17972             sigchan = atoi(v->value);
17973             res = linkset_addsigchan(sigchan);
17974             if (res < 0)
17975                return -1;
17976 
17977          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17978             struct dahdi_ss7 *link;
17979             link = ss7_resolve_linkset(cur_linkset);
17980             if (!link) {
17981                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17982                return -1;
17983             }
17984             if (ast_true(v->value))
17985                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17986 #endif   /* defined(HAVE_SS7) */
17987 #ifdef HAVE_OPENR2
17988          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17989             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17990             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);
17991          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17992             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17993          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17994             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17995             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17996                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17997                confp->mfcr2.variant = OR2_VAR_ITU;
17998             }
17999          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
18000             confp->mfcr2.mfback_timeout = atoi(v->value);
18001             if (!confp->mfcr2.mfback_timeout) {
18002                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
18003                confp->mfcr2.mfback_timeout = -1;
18004             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
18005                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
18006             }
18007          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
18008             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
18009             if (confp->mfcr2.metering_pulse_timeout > 500) {
18010                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
18011             }
18012          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
18013             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
18014          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
18015             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
18016          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
18017             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
18018          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
18019             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
18020          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
18021             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
18022          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
18023             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
18024          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
18025             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
18026 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
18027          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
18028             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
18029 #endif
18030          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
18031             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
18032          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
18033             confp->mfcr2.max_ani = atoi(v->value);
18034             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
18035                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
18036             }
18037          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
18038             confp->mfcr2.max_dnis = atoi(v->value);
18039             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
18040                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
18041             }
18042          } else if (!strcasecmp(v->name, "mfcr2_category")) {
18043             confp->mfcr2.category = openr2_proto_get_category(v->value);
18044             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
18045                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
18046                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
18047                      v->value, v->lineno);
18048             }
18049          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
18050             openr2_log_level_t tmplevel;
18051             char *clevel;
18052             char *logval = ast_strdupa(v->value);
18053             while (logval) {
18054                clevel = strsep(&logval,",");
18055                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
18056                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
18057                   continue;
18058                }
18059                confp->mfcr2.loglevel |= tmplevel;
18060             }
18061 #endif /* HAVE_OPENR2 */
18062          } else if (!strcasecmp(v->name, "cadence")) {
18063             /* setup to scan our argument */
18064             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
18065             int i;
18066             struct dahdi_ring_cadence new_cadence;
18067             int cid_location = -1;
18068             int firstcadencepos = 0;
18069             char original_args[80];
18070             int cadence_is_ok = 1;
18071 
18072             ast_copy_string(original_args, v->value, sizeof(original_args));
18073             /* 16 cadences allowed (8 pairs) */
18074             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]);
18075 
18076             /* Cadence must be even (on/off) */
18077             if (element_count % 2 == 1) {
18078                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18079                cadence_is_ok = 0;
18080             }
18081 
18082             /* Ring cadences cannot be negative */
18083             for (i = 0; i < element_count; i++) {
18084                if (c[i] == 0) {
18085                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18086                   cadence_is_ok = 0;
18087                   break;
18088                } else if (c[i] < 0) {
18089                   if (i % 2 == 1) {
18090                      /* Silence duration, negative possibly okay */
18091                      if (cid_location == -1) {
18092                         cid_location = i;
18093                         c[i] *= -1;
18094                      } else {
18095                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18096                         cadence_is_ok = 0;
18097                         break;
18098                      }
18099                   } else {
18100                      if (firstcadencepos == 0) {
18101                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
18102                                  /* duration will be passed negative to the DAHDI driver */
18103                      } else {
18104                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18105                         cadence_is_ok = 0;
18106                         break;
18107                      }
18108                   }
18109                }
18110             }
18111 
18112             /* Substitute our scanned cadence */
18113             for (i = 0; i < 16; i++) {
18114                new_cadence.ringcadence[i] = c[i];
18115             }
18116 
18117             if (cadence_is_ok) {
18118                /* ---we scanned it without getting annoyed; now some sanity checks--- */
18119                if (element_count < 2) {
18120                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18121                } else {
18122                   if (cid_location == -1) {
18123                      /* user didn't say; default to first pause */
18124                      cid_location = 1;
18125                   } else {
18126                      /* convert element_index to cidrings value */
18127                      cid_location = (cid_location + 1) / 2;
18128                   }
18129                   /* ---we like their cadence; try to install it--- */
18130                   if (!user_has_defined_cadences++)
18131                      /* this is the first user-defined cadence; clear the default user cadences */
18132                      num_cadence = 0;
18133                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
18134                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18135                   else {
18136                      cadences[num_cadence] = new_cadence;
18137                      cidrings[num_cadence++] = cid_location;
18138                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18139                   }
18140                }
18141             }
18142          } else if (!strcasecmp(v->name, "ringtimeout")) {
18143             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18144          } else if (!strcasecmp(v->name, "prewink")) {
18145             confp->timing.prewinktime = atoi(v->value);
18146          } else if (!strcasecmp(v->name, "preflash")) {
18147             confp->timing.preflashtime = atoi(v->value);
18148          } else if (!strcasecmp(v->name, "wink")) {
18149             confp->timing.winktime = atoi(v->value);
18150          } else if (!strcasecmp(v->name, "flash")) {
18151             confp->timing.flashtime = atoi(v->value);
18152          } else if (!strcasecmp(v->name, "start")) {
18153             confp->timing.starttime = atoi(v->value);
18154          } else if (!strcasecmp(v->name, "rxwink")) {
18155             confp->timing.rxwinktime = atoi(v->value);
18156          } else if (!strcasecmp(v->name, "rxflash")) {
18157             confp->timing.rxflashtime = atoi(v->value);
18158          } else if (!strcasecmp(v->name, "debounce")) {
18159             confp->timing.debouncetime = atoi(v->value);
18160          } else if (!strcasecmp(v->name, "toneduration")) {
18161             int toneduration;
18162             int ctlfd;
18163             int res;
18164             struct dahdi_dialparams dps;
18165 
18166             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18167             if (ctlfd == -1) {
18168                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18169                return -1;
18170             }
18171 
18172             toneduration = atoi(v->value);
18173             if (toneduration > -1) {
18174                memset(&dps, 0, sizeof(dps));
18175 
18176                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18177                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18178                if (res < 0) {
18179                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18180                   close(ctlfd);
18181                   return -1;
18182                }
18183             }
18184             close(ctlfd);
18185          } else if (!strcasecmp(v->name, "defaultcic")) {
18186             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18187          } else if (!strcasecmp(v->name, "defaultozz")) {
18188             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18189          } else if (!strcasecmp(v->name, "mwilevel")) {
18190             mwilevel = atoi(v->value);
18191          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18192             dtmfcid_level = atoi(v->value);
18193          } else if (!strcasecmp(v->name, "reportalarms")) {
18194             if (!strcasecmp(v->value, "all"))
18195                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18196             if (!strcasecmp(v->value, "none"))
18197                report_alarms = 0;
18198             else if (!strcasecmp(v->value, "channels"))
18199                report_alarms = REPORT_CHANNEL_ALARMS;
18200             else if (!strcasecmp(v->value, "spans"))
18201                report_alarms = REPORT_SPAN_ALARMS;
18202           }
18203       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18204          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18205    }
18206 
18207    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
18208    if (confp->chan.vars) {
18209       ast_variables_destroy(confp->chan.vars);
18210       confp->chan.vars = NULL;
18211    }
18212 
18213    if (dahdichan) {
18214       /* Process the deferred dahdichan value. */
18215       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18216          &found_pseudo)) {
18217          if (confp->ignore_failed_channels) {
18218             ast_log(LOG_WARNING,
18219                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18220                dahdichan->value);
18221          } else {
18222             return -1;
18223          }
18224       }
18225    }
18226 
18227    /* mark the first channels of each DAHDI span to watch for their span alarms */
18228    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18229       if (!tmp->destroy && tmp->span != y) {
18230          tmp->manages_span_alarms = 1;
18231          y = tmp->span; 
18232       } else {
18233          tmp->manages_span_alarms = 0;
18234       }
18235    }
18236 
18237    /*< \todo why check for the pseudo in the per-channel section.
18238     * Any actual use for manual setup of the pseudo channel? */
18239    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18240       /* use the default configuration for a channel, so
18241          that any settings from real configured channels
18242          don't "leak" into the pseudo channel config
18243       */
18244       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18245 
18246       if (conf.chan.cc_params) {
18247          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18248       } else {
18249          tmp = NULL;
18250       }
18251       if (tmp) {
18252          ast_verb(3, "Automatically generated pseudo channel\n");
18253       } else {
18254          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18255       }
18256       ast_cc_config_params_destroy(conf.chan.cc_params);
18257    }
18258    return 0;
18259 }

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

Definition at line 17086 of file chan_dahdi.c.

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

Referenced by process_dahdi().

17087 {
17088    char *parse = ast_strdupa(data);
17089    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17090    unsigned int param_count;
17091    unsigned int x;
17092 
17093    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17094       return;
17095 
17096    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17097 
17098    /* first parameter is tap length, process it here */
17099 
17100    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17101 
17102    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17103       confp->chan.echocancel.head.tap_length = x;
17104    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17105       confp->chan.echocancel.head.tap_length = 128;
17106 
17107    /* now process any remaining parameters */
17108 
17109    for (x = 1; x < param_count; x++) {
17110       struct {
17111          char *name;
17112          char *value;
17113       } param;
17114 
17115       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
17116          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
17117          continue;
17118       }
17119 
17120       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17121          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
17122          continue;
17123       }
17124 
17125       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17126 
17127       if (param.value) {
17128          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17129             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
17130             continue;
17131          }
17132       }
17133       confp->chan.echocancel.head.param_count++;
17134    }
17135 }

static int reload ( void   )  [static]

Definition at line 18937 of file chan_dahdi.c.

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

18938 {
18939    int res = 0;
18940 
18941    res = setup_dahdi(1);
18942    if (res) {
18943       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18944       return -1;
18945    }
18946    return 0;
18947 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

Definition at line 4846 of file chan_dahdi.c.

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

Referenced by dahdi_hangup(), and my_all_subchannels_hungup().

04847 {
04848    p->confno = -1;
04849    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04850    if (p->subs[SUB_REAL].dfd > -1) {
04851       struct dahdi_confinfo zi;
04852 
04853       memset(&zi, 0, sizeof(zi));
04854       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04855          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04856    }
04857    return 0;
04858 }

static int restart_monitor ( void   )  [static]

Definition at line 12030 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, and LOG_WARNING.

Referenced by dahdi_hangup(), dahdi_request(), my_all_subchannels_hungup(), and setup_dahdi_int().

12031 {
12032    /* If we're supposed to be stopped -- stay stopped */
12033    if (monitor_thread == AST_PTHREADT_STOP)
12034       return 0;
12035    ast_mutex_lock(&monlock);
12036    if (monitor_thread == pthread_self()) {
12037       ast_mutex_unlock(&monlock);
12038       ast_log(LOG_WARNING, "Cannot kill myself\n");
12039       return -1;
12040    }
12041    if (monitor_thread != AST_PTHREADT_NULL) {
12042       /* Wake up the thread */
12043       pthread_kill(monitor_thread, SIGURG);
12044    } else {
12045       /* Start a new monitor */
12046       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12047          ast_mutex_unlock(&monlock);
12048          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12049          return -1;
12050       }
12051    }
12052    ast_mutex_unlock(&monlock);
12053    return 0;
12054 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

Definition at line 5271 of file chan_dahdi.c.

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

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

05272 {
05273    int res;
05274    if (p->saveconf.confmode) {
05275       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05276       p->saveconf.confmode = 0;
05277       if (res) {
05278          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05279          return -1;
05280       }
05281       ast_debug(1, "Restored conferencing\n");
05282    }
05283    return 0;
05284 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

Definition at line 5178 of file chan_dahdi.c.

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

05179 {
05180    int res;
05181 
05182    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05183    if (res) {
05184       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05185       return -1;
05186    }
05187 
05188    return 0;
05189 }

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

Definition at line 6169 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_hangup().

06170 {
06171    if (p->bufferoverrideinuse) {
06172       /* faxbuffers are in use, revert them */
06173       struct dahdi_bufferinfo bi = {
06174          .txbufpolicy = p->buf_policy,
06175          .rxbufpolicy = p->buf_policy,
06176          .bufsize = p->bufsize,
06177          .numbufs = p->buf_no
06178       };
06179       int bpres;
06180 
06181       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06182          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06183       }
06184       p->bufferoverrideinuse = 0;
06185       return bpres;
06186    }
06187 
06188    return -1;
06189 }

static int save_conference ( struct dahdi_pvt p  )  [static]

Definition at line 5245 of file chan_dahdi.c.

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

Referenced by dahdi_callwait(), dahdi_handle_event(), and my_callwait().

05246 {
05247    struct dahdi_confinfo c;
05248    int res;
05249    if (p->saveconf.confmode) {
05250       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05251       return -1;
05252    }
05253    p->saveconf.chan = 0;
05254    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05255    if (res) {
05256       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05257       p->saveconf.confmode = 0;
05258       return -1;
05259    }
05260    memset(&c, 0, sizeof(c));
05261    c.confmode = DAHDI_CONF_NORMAL;
05262    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05263    if (res) {
05264       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05265       return -1;
05266    }
05267    ast_debug(1, "Disabled conferencing\n");
05268    return 0;
05269 }

static int send_callerid ( struct dahdi_pvt p  )  [static]

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

05330 {
05331    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05332    int res;
05333    /* Take out of linear mode if necessary */
05334    if (p->subs[SUB_REAL].linear) {
05335       p->subs[SUB_REAL].linear = 0;
05336       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05337    }
05338    while (p->cidpos < p->cidlen) {
05339       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05340       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05341       if (res < 0) {
05342          if (errno == EAGAIN)
05343             return 0;
05344          else {
05345             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05346             return -1;
05347          }
05348       }
05349       if (!res)
05350          return 0;
05351       p->cidpos += res;
05352    }
05353    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05354    ast_free(p->cidspill);
05355    p->cidspill = NULL;
05356    if (p->callwaitcas) {
05357       /* Wait for CID/CW to expire */
05358       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05359       p->cid_suppress_expire = p->cidcwexpire;
05360    } else
05361       restore_conference(p);
05362    return 0;
05363 }

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

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

05287 {
05288    p->callwaitcas = 0;
05289    p->cidcwexpire = 0;
05290    p->cid_suppress_expire = 0;
05291    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05292       return -1;
05293    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05294    /* Make sure we account for the end */
05295    p->cidlen += READ_SIZE * 4;
05296    p->cidpos = 0;
05297    send_callerid(p);
05298    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05299    return 0;
05300 }

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

Definition at line 5159 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

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

05160 {
05161    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05162 }

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

Definition at line 5142 of file chan_dahdi.c.

References ast_debug, errno, and fill_rxgain().

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

05143 {
05144    struct dahdi_gains g;
05145    int res;
05146 
05147    memset(&g, 0, sizeof(g));
05148    res = ioctl(fd, DAHDI_GETGAINS, &g);
05149    if (res) {
05150       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05151       return res;
05152    }
05153 
05154    fill_rxgain(&g, gain, drc, law);
05155 
05156    return ioctl(fd, DAHDI_SETGAINS, &g);
05157 }

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

Definition at line 5125 of file chan_dahdi.c.

References ast_debug, errno, and fill_txgain().

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

05126 {
05127    struct dahdi_gains g;
05128    int res;
05129 
05130    memset(&g, 0, sizeof(g));
05131    res = ioctl(fd, DAHDI_GETGAINS, &g);
05132    if (res) {
05133       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05134       return res;
05135    }
05136 
05137    fill_txgain(&g, gain, drc, law);
05138 
05139    return ioctl(fd, DAHDI_SETGAINS, &g);
05140 }

static int setup_dahdi ( int  reload  )  [static]

Definition at line 18580 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 dahdi_restart(), load_module(), and reload().

18581 {
18582    int res;
18583    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18584    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18585    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18586 
18587    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18588       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18589    } else {
18590       res = -1;
18591    }
18592    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18593    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18594    ast_cc_config_params_destroy(conf.chan.cc_params);
18595 
18596    return res;
18597 }

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 18293 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_pthread_create, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, deep_copy_dahdi_chan_conf(), global_jbconf, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sig_ss7_linkset::master, ast_variable::name, ast_variable::next, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_dahdi(), sig_pri_span::pvts, restart_monitor(), sig_pri_start_pri(), sig_ss7_linkset::ss7, ss7_linkset(), and ast_variable::value.

Referenced by setup_dahdi().

18294 {
18295    struct ast_config *cfg;
18296    struct ast_config *ucfg;
18297    struct ast_variable *v;
18298    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18299    const char *chans;
18300    const char *cat;
18301    int res;
18302 
18303 #ifdef HAVE_PRI
18304    char *c;
18305    int spanno;
18306    int i;
18307    int logicalspan;
18308    int trunkgroup;
18309    int dchannels[SIG_PRI_NUM_DCHANS];
18310 #endif
18311    int have_cfg_now;
18312    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
18313 
18314    cfg = ast_config_load(config, config_flags);
18315    have_cfg_now = !!cfg;
18316    if (!cfg) {
18317       /* Error if we have no config file */
18318       if (had_cfg_before) {
18319          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18320          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18321       }
18322       cfg = ast_config_new();/* Dummy config */
18323       if (!cfg) {
18324          return 0;
18325       }
18326       ucfg = ast_config_load("users.conf", config_flags);
18327       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18328          ast_config_destroy(cfg);
18329          return 0;
18330       }
18331       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18332          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18333          ast_config_destroy(cfg);
18334          return 0;
18335       }
18336    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18337       ucfg = ast_config_load("users.conf", config_flags);
18338       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18339          return 0;
18340       }
18341       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18342          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18343          return 0;
18344       }
18345       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18346       cfg = ast_config_load(config, config_flags);
18347       have_cfg_now = !!cfg;
18348       if (!cfg) {
18349          if (had_cfg_before) {
18350             /* We should have been able to load the config. */
18351             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18352             ast_config_destroy(ucfg);
18353             return 0;
18354          }
18355          cfg = ast_config_new();/* Dummy config */
18356          if (!cfg) {
18357             ast_config_destroy(ucfg);
18358             return 0;
18359          }
18360       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18361          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18362          ast_config_destroy(ucfg);
18363          return 0;
18364       }
18365    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18366       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18367       return 0;
18368    } else {
18369       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18370       ucfg = ast_config_load("users.conf", config_flags);
18371       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18372          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18373          ast_config_destroy(cfg);
18374          return 0;
18375       }
18376    }
18377    had_cfg_before = have_cfg_now;
18378 
18379    /* It's a little silly to lock it, but we might as well just to be sure */
18380    ast_mutex_lock(&iflock);
18381 #ifdef HAVE_PRI
18382    if (reload != 1) {
18383       /* Process trunkgroups first */
18384       v = ast_variable_browse(cfg, "trunkgroups");
18385       while (v) {
18386          if (!strcasecmp(v->name, "trunkgroup")) {
18387             trunkgroup = atoi(v->value);
18388             if (trunkgroup > 0) {
18389                if ((c = strchr(v->value, ','))) {
18390                   i = 0;
18391                   memset(dchannels, 0, sizeof(dchannels));
18392                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18393                      dchannels[i] = atoi(c + 1);
18394                      if (dchannels[i] < 0) {
18395                         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);
18396                      } else
18397                         i++;
18398                      c = strchr(c + 1, ',');
18399                   }
18400                   if (i) {
18401                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18402                         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);
18403                   } else
18404                         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");
18405                   } else
18406                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18407                } else
18408                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18409             } else
18410                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18411          } else if (!strcasecmp(v->name, "spanmap")) {
18412             spanno = atoi(v->value);
18413             if (spanno > 0) {
18414                if ((c = strchr(v->value, ','))) {
18415                   trunkgroup = atoi(c + 1);
18416                   if (trunkgroup > 0) {
18417                      if ((c = strchr(c + 1, ',')))
18418                         logicalspan = atoi(c + 1);
18419                      else
18420                         logicalspan = 0;
18421                      if (logicalspan >= 0) {
18422                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18423                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18424                      } else
18425                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18426                      } else
18427                         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);
18428                   } else
18429                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18430                } else
18431                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18432             } else
18433                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18434          } else {
18435             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18436          }
18437          v = v->next;
18438       }
18439    }
18440 #endif
18441 
18442    /* Copy the default jb config over global_jbconf */
18443    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18444 
18445    mwimonitornotify[0] = '\0';
18446 
18447    v = ast_variable_browse(cfg, "channels");
18448    if ((res = process_dahdi(base_conf,
18449       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18450       v, reload, 0))) {
18451       ast_mutex_unlock(&iflock);
18452       ast_config_destroy(cfg);
18453       if (ucfg) {
18454          ast_config_destroy(ucfg);
18455       }
18456       return res;
18457    }
18458 
18459    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18460    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18461       /* [channels] and [trunkgroups] are used. Let's also reserve
18462        * [globals] and [general] for future use
18463        */
18464       if (!strcasecmp(cat, "general") ||
18465          !strcasecmp(cat, "trunkgroups") ||
18466          !strcasecmp(cat, "globals") ||
18467          !strcasecmp(cat, "channels")) {
18468          continue;
18469       }
18470 
18471       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18472       if (ast_strlen_zero(chans)) {
18473          /* Section is useless without a dahdichan value present. */
18474          continue;
18475       }
18476 
18477       /* Copy base_conf to conf. */
18478       deep_copy_dahdi_chan_conf(conf, base_conf);
18479 
18480       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18481          ast_mutex_unlock(&iflock);
18482          ast_config_destroy(cfg);
18483          if (ucfg) {
18484             ast_config_destroy(ucfg);
18485          }
18486          return res;
18487       }
18488    }
18489 
18490    ast_config_destroy(cfg);
18491 
18492    if (ucfg) {
18493       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18494       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18495       process_dahdi(base_conf,
18496          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18497          ast_variable_browse(ucfg, "general"), 1, 0);
18498 
18499       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18500          if (!strcasecmp(cat, "general")) {
18501             continue;
18502          }
18503 
18504          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18505          if (ast_strlen_zero(chans)) {
18506             /* Section is useless without a dahdichan value present. */
18507             continue;
18508          }
18509 
18510          /* Copy base_conf to conf. */
18511          deep_copy_dahdi_chan_conf(conf, base_conf);
18512 
18513          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18514             ast_config_destroy(ucfg);
18515             ast_mutex_unlock(&iflock);
18516             return res;
18517          }
18518       }
18519       ast_config_destroy(ucfg);
18520    }
18521    ast_mutex_unlock(&iflock);
18522 
18523 #ifdef HAVE_PRI
18524    if (reload != 1) {
18525       int x;
18526       for (x = 0; x < NUM_SPANS; x++) {
18527          if (pris[x].pri.pvts[0]) {
18528             prepare_pri(pris + x);
18529             if (sig_pri_start_pri(&pris[x].pri)) {
18530                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18531                return -1;
18532             } else
18533                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18534          }
18535       }
18536    }
18537 #endif
18538 #if defined(HAVE_SS7)
18539    if (reload != 1) {
18540       int x;
18541       for (x = 0; x < NUM_SPANS; x++) {
18542          if (linksets[x].ss7.ss7) {
18543             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18544             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18545                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18546                return -1;
18547             } else
18548                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18549          }
18550       }
18551    }
18552 #endif   /* defined(HAVE_SS7) */
18553 #ifdef HAVE_OPENR2
18554    if (reload != 1) {
18555       int x;
18556       for (x = 0; x < r2links_count; x++) {
18557          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18558             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18559             return -1;
18560          } else {
18561             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18562          }
18563       }
18564    }
18565 #endif
18566    /* And start the monitor for the first time */
18567    restart_monitor();
18568    return 0;
18569 }

static int sigtype_to_signalling ( int  sigtype  )  [static]

Definition at line 12313 of file chan_dahdi.c.

Referenced by mkintf().

12314 {
12315    return sigtype;
12316 }

static void string_replace ( char *  str,
int  char1,
int  char2 
) [static]

Definition at line 16990 of file chan_dahdi.c.

Referenced by parse_spanchan().

16991 {
16992    for (; *str; str++) {
16993       if (*str == char1) {
16994          *str = char2;
16995       }
16996    }
16997 }

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

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

04342 {
04343    int tchan;
04344    int tinthreeway;
04345    struct ast_channel *towner;
04346 
04347    ast_debug(1, "Swapping %d and %d\n", a, b);
04348 
04349    tchan = p->subs[a].chan;
04350    towner = p->subs[a].owner;
04351    tinthreeway = p->subs[a].inthreeway;
04352 
04353    p->subs[a].chan = p->subs[b].chan;
04354    p->subs[a].owner = p->subs[b].owner;
04355    p->subs[a].inthreeway = p->subs[b].inthreeway;
04356 
04357    p->subs[b].chan = tchan;
04358    p->subs[b].owner = towner;
04359    p->subs[b].inthreeway = tinthreeway;
04360 
04361    if (p->subs[a].owner)
04362       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04363    if (p->subs[b].owner)
04364       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04365    wakeup_sub(p, a);
04366    wakeup_sub(p, b);
04367 }

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

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

04488 {
04489    if (!x) {
04490       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04491       return -1;
04492    }
04493    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04494    dahdi_close_sub(p, x);
04495    p->subs[x].linear = 0;
04496    p->subs[x].chan = 0;
04497    p->subs[x].owner = NULL;
04498    p->subs[x].inthreeway = 0;
04499    p->polarity = POLARITY_IDLE;
04500    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04501    return 0;
04502 }

static int unload_module ( void   )  [static]

Definition at line 16974 of file chan_dahdi.c.

References __unload_module(), ast_mutex_destroy, sig_ss7_linkset::lock, and sig_pri_span::lock.

16975 {
16976 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16977    int y;
16978 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16979 #ifdef HAVE_PRI
16980    for (y = 0; y < NUM_SPANS; y++)
16981       ast_mutex_destroy(&pris[y].pri.lock);
16982 #endif
16983 #if defined(HAVE_SS7)
16984    for (y = 0; y < NUM_SPANS; y++)
16985       ast_mutex_destroy(&linksets[y].ss7.lock);
16986 #endif   /* defined(HAVE_SS7) */
16987    return __unload_module();
16988 }

static int update_conf ( struct dahdi_pvt p  )  [static]

Definition at line 4860 of file chan_dahdi.c.

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

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

04861 {
04862    int needconf = 0;
04863    int x;
04864    int useslavenative;
04865    struct dahdi_pvt *slave = NULL;
04866 
04867    useslavenative = isslavenative(p, &slave);
04868    /* Start with the obvious, general stuff */
04869    for (x = 0; x < 3; x++) {
04870       /* Look for three way calls */
04871       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04872          conf_add(p, &p->subs[x], x, 0);
04873          needconf++;
04874       } else {
04875          conf_del(p, &p->subs[x], x);
04876       }
04877    }
04878    /* If we have a slave, add him to our conference now. or DAX
04879       if this is slave native */
04880    for (x = 0; x < MAX_SLAVES; x++) {
04881       if (p->slaves[x]) {
04882          if (useslavenative)
04883             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04884          else {
04885             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04886             needconf++;
04887          }
04888       }
04889    }
04890    /* If we're supposed to be in there, do so now */
04891    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04892       if (useslavenative)
04893          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04894       else {
04895          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04896          needconf++;
04897       }
04898    }
04899    /* If we have a master, add ourselves to his conference */
04900    if (p->master) {
04901       if (isslavenative(p->master, NULL)) {
04902          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04903       } else {
04904          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04905       }
04906    }
04907    if (!needconf) {
04908       /* Nobody is left (or should be left) in our conference.
04909          Kill it. */
04910       p->confno = -1;
04911    }
04912    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04913    return 0;
04914 }

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

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

03849 {
03850    dahdi_lock_sub_owner(p, a);
03851    if (p->subs[a].owner) {
03852       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03853       ast_channel_unlock(p->subs[a].owner);
03854    }
03855 }


Variable Documentation

int alarm

Definition at line 4637 of file chan_dahdi.c.

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

Referenced by alarm2str().

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

Definition at line 412 of file chan_dahdi.c.

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

Definition at line 393 of file chan_dahdi.c.

int cidrings[NUM_CADENCE_MAX] [static]

cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.

Definition at line 404 of file chan_dahdi.c.

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

Definition at line 347 of file chan_dahdi.c.

Definition at line 3724 of file chan_dahdi.c.

Initial value:

Definition at line 18740 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

Definition at line 16042 of file chan_dahdi.c.

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

Initial value:

Definition at line 18735 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 1521 of file chan_dahdi.c.

Initial value:

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

char defaultcic[64] = "" [static]

Definition at line 420 of file chan_dahdi.c.

char defaultozz[64] = "" [static]

Definition at line 421 of file chan_dahdi.c.

int distinctiveringaftercid = 0 [static]

Definition at line 432 of file chan_dahdi.c.

int dtmfcid_level = 256 [static]

Definition at line 437 of file chan_dahdi.c.

const char* const events[] [static]

Definition at line 4614 of file chan_dahdi.c.

int firstdigittimeout = 16000 [static]

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

Definition at line 449 of file chan_dahdi.c.

Referenced by disa_exec().

int gendigittimeout = 8000 [static]

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

Definition at line 452 of file chan_dahdi.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 304 of file chan_dahdi.c.

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

int ifcount = 0 [static]

Definition at line 461 of file chan_dahdi.c.

struct dahdi_pvt* ifend = NULL [static]

Main interface list end

Definition at line 1323 of file chan_dahdi.c.

struct dahdi_pvt* iflist = NULL [static]

Main interface list start

Definition at line 1322 of file chan_dahdi.c.

const char* const lbostr[] [static]

Definition at line 283 of file chan_dahdi.c.

int matchdigittimeout = 3000 [static]

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

Definition at line 455 of file chan_dahdi.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

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

Definition at line 473 of file chan_dahdi.c.

int mwilevel = 512 [static]

Definition at line 436 of file chan_dahdi.c.

char mwimonitornotify[PATH_MAX] = "" [static]

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

Definition at line 424 of file chan_dahdi.c.

int mwisend_rpas = 0 [static]

Definition at line 426 of file chan_dahdi.c.

char* name

Definition at line 4638 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 390 of file chan_dahdi.c.

int num_restart_pending = 0 [static]

Definition at line 478 of file chan_dahdi.c.

int numbufs = 4 [static]

Definition at line 434 of file chan_dahdi.c.

char progzone[10] = "" [static]

Definition at line 429 of file chan_dahdi.c.

int report_alarms = REPORT_CHANNEL_ALARMS [static]

Definition at line 441 of file chan_dahdi.c.

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

struct dahdi_pvt* round_robin[32] [static]

Round robin search locations.

Definition at line 3795 of file chan_dahdi.c.

Definition at line 474 of file chan_dahdi.c.

int ss_thread_count = 0 [static]

Definition at line 477 of file chan_dahdi.c.

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

Definition at line 635 of file chan_dahdi.c.

const char tdesc[] = "DAHDI Telephony Driver" [static]

Definition at line 326 of file chan_dahdi.c.

int usedistinctiveringdetection = 0 [static]

Definition at line 431 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 391 of file chan_dahdi.c.


Generated on 31 Aug 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1