Tue Aug 20 16:34:50 2013

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 %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define FORMAT2   "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT2   "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define GET_CHANNEL(p)   ((p)->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 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 658 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

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

Definition at line 1543 of file chan_dahdi.c.

Referenced by my_complete_conference_update(), and update_conf().

#define HANGUP   1

Definition at line 15919 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 16941 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 16995 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 16997 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 613 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 682 of file chan_dahdi.c.

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

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

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


Function Documentation

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

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

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

static int __unload_module ( void   )  [static]

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

16742 {
16743    struct dahdi_pvt *p;
16744 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16745    int i, j;
16746 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16747 
16748 #ifdef HAVE_PRI
16749    for (i = 0; i < NUM_SPANS; i++) {
16750       if (pris[i].pri.master != AST_PTHREADT_NULL)
16751          pthread_cancel(pris[i].pri.master);
16752    }
16753    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16754    ast_unregister_application(dahdi_send_keypad_facility_app);
16755 #ifdef HAVE_PRI_PROG_W_CAUSE
16756    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16757 #endif
16758 #endif
16759 #if defined(HAVE_SS7)
16760    for (i = 0; i < NUM_SPANS; i++) {
16761       if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16762          pthread_cancel(linksets[i].ss7.master);
16763       }
16764    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16765 #endif   /* defined(HAVE_SS7) */
16766 #if defined(HAVE_OPENR2)
16767    dahdi_r2_destroy_links();
16768    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16769    ast_unregister_application(dahdi_accept_r2_call_app);
16770 #endif
16771 
16772    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16773    ast_manager_unregister("DAHDIDialOffhook");
16774    ast_manager_unregister("DAHDIHangup");
16775    ast_manager_unregister("DAHDITransfer");
16776    ast_manager_unregister("DAHDIDNDoff");
16777    ast_manager_unregister("DAHDIDNDon");
16778    ast_manager_unregister("DAHDIShowChannels");
16779    ast_manager_unregister("DAHDIRestart");
16780    ast_data_unregister(NULL);
16781    ast_channel_unregister(&dahdi_tech);
16782 
16783    /* Hangup all interfaces if they have an owner */
16784    ast_mutex_lock(&iflock);
16785    for (p = iflist; p; p = p->next) {
16786       if (p->owner)
16787          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16788    }
16789    ast_mutex_unlock(&iflock);
16790 
16791    ast_mutex_lock(&monlock);
16792    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16793       pthread_cancel(monitor_thread);
16794       pthread_kill(monitor_thread, SIGURG);
16795       pthread_join(monitor_thread, NULL);
16796    }
16797    monitor_thread = AST_PTHREADT_STOP;
16798    ast_mutex_unlock(&monlock);
16799 
16800    destroy_all_channels();
16801 
16802 #if defined(HAVE_PRI)
16803    for (i = 0; i < NUM_SPANS; i++) {
16804       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16805          pthread_join(pris[i].pri.master, NULL);
16806       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16807          dahdi_close_pri_fd(&(pris[i]), j);
16808       }
16809       sig_pri_stop_pri(&pris[i].pri);
16810    }
16811 #if defined(HAVE_PRI_CCSS)
16812    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16813    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16814 #endif   /* defined(HAVE_PRI_CCSS) */
16815    sig_pri_unload();
16816 #endif
16817 
16818 #if defined(HAVE_SS7)
16819    for (i = 0; i < NUM_SPANS; i++) {
16820       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16821          pthread_join(linksets[i].ss7.master, NULL);
16822       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16823          dahdi_close_ss7_fd(&(linksets[i]), j);
16824       }
16825    }
16826 #endif   /* defined(HAVE_SS7) */
16827    ast_cond_destroy(&ss_thread_complete);
16828    return 0;
16829 }

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

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

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

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

16057 {
16058    struct dahdi_pvt *p;
16059    const char *channel = astman_get_header(m, "DAHDIChannel");
16060    const char *number = astman_get_header(m, "Number");
16061    int i;
16062 
16063    if (ast_strlen_zero(channel)) {
16064       astman_send_error(s, m, "No channel specified");
16065       return 0;
16066    }
16067    if (ast_strlen_zero(number)) {
16068       astman_send_error(s, m, "No number specified");
16069       return 0;
16070    }
16071    p = find_channel_from_str(channel);
16072    if (!p) {
16073       astman_send_error(s, m, "No such channel");
16074       return 0;
16075    }
16076    if (!p->owner) {
16077       astman_send_error(s, m, "Channel does not have it's owner");
16078       return 0;
16079    }
16080    for (i = 0; i < strlen(number); i++) {
16081       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16082       dahdi_queue_frame(p, &f);
16083    }
16084    astman_send_ack(s, m, "DAHDIDialOffhook");
16085    return 0;
16086 }

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

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

15992 {
15993    struct dahdi_pvt *p;
15994    const char *channel = astman_get_header(m, "DAHDIChannel");
15995 
15996    if (ast_strlen_zero(channel)) {
15997       astman_send_error(s, m, "No channel specified");
15998       return 0;
15999    }
16000    p = find_channel_from_str(channel);
16001    if (!p) {
16002       astman_send_error(s, m, "No such channel");
16003       return 0;
16004    }
16005    dahdi_dnd(p, 0);
16006    astman_send_ack(s, m, "DND Disabled");
16007    return 0;
16008 }

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

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

15973 {
15974    struct dahdi_pvt *p;
15975    const char *channel = astman_get_header(m, "DAHDIChannel");
15976 
15977    if (ast_strlen_zero(channel)) {
15978       astman_send_error(s, m, "No channel specified");
15979       return 0;
15980    }
15981    p = find_channel_from_str(channel);
15982    if (!p) {
15983       astman_send_error(s, m, "No such channel");
15984       return 0;
15985    }
15986    dahdi_dnd(p, 1);
15987    astman_send_ack(s, m, "DND Enabled");
15988    return 0;
15989 }

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

Definition at line 15254 of file chan_dahdi.c.

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

Referenced by load_module().

15255 {
15256    if (dahdi_restart() != 0) {
15257       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15258       return 1;
15259    }
15260    astman_send_ack(s, m, "DAHDIRestart: Success");
15261    return 0;
15262 }

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

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

16089 {
16090    struct dahdi_pvt *tmp = NULL;
16091    const char *id = astman_get_header(m, "ActionID");
16092    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16093    char idText[256] = "";
16094    int channels = 0;
16095    int dahdichanquery;
16096 
16097    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16098       /* Not numeric string. */
16099       dahdichanquery = -1;
16100    }
16101 
16102    astman_send_ack(s, m, "DAHDI channel status will follow");
16103    if (!ast_strlen_zero(id))
16104       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16105 
16106    ast_mutex_lock(&iflock);
16107 
16108    for (tmp = iflist; tmp; tmp = tmp->next) {
16109       if (tmp->channel > 0) {
16110          int alm;
16111 
16112          /* If a specific channel is queried for, only deliver status for that channel */
16113          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16114             continue;
16115 
16116          alm = get_alarms(tmp);
16117          channels++;
16118          if (tmp->owner) {
16119             /* Add data if we have a current call */
16120             astman_append(s,
16121                "Event: DAHDIShowChannels\r\n"
16122                "DAHDIChannel: %d\r\n"
16123                "Channel: %s\r\n"
16124                "Uniqueid: %s\r\n"
16125                "AccountCode: %s\r\n"
16126                "Signalling: %s\r\n"
16127                "SignallingCode: %d\r\n"
16128                "Context: %s\r\n"
16129                "DND: %s\r\n"
16130                "Alarm: %s\r\n"
16131                "%s"
16132                "\r\n",
16133                tmp->channel,
16134                tmp->owner->name,
16135                tmp->owner->uniqueid,
16136                tmp->owner->accountcode,
16137                sig2str(tmp->sig),
16138                tmp->sig,
16139                tmp->context,
16140                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16141                alarm2str(alm), idText);
16142          } else {
16143             astman_append(s,
16144                "Event: DAHDIShowChannels\r\n"
16145                "DAHDIChannel: %d\r\n"
16146                "Signalling: %s\r\n"
16147                "SignallingCode: %d\r\n"
16148                "Context: %s\r\n"
16149                "DND: %s\r\n"
16150                "Alarm: %s\r\n"
16151                "%s"
16152                "\r\n",
16153                tmp->channel, sig2str(tmp->sig), tmp->sig,
16154                tmp->context,
16155                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16156                alarm2str(alm), idText);
16157          }
16158       }
16159    }
16160 
16161    ast_mutex_unlock(&iflock);
16162 
16163    astman_append(s,
16164       "Event: DAHDIShowChannelsComplete\r\n"
16165       "%s"
16166       "Items: %d\r\n"
16167       "\r\n",
16168       idText,
16169       channels);
16170    return 0;
16171 }

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

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

16011 {
16012    struct dahdi_pvt *p;
16013    const char *channel = astman_get_header(m, "DAHDIChannel");
16014 
16015    if (ast_strlen_zero(channel)) {
16016       astman_send_error(s, m, "No channel specified");
16017       return 0;
16018    }
16019    p = find_channel_from_str(channel);
16020    if (!p) {
16021       astman_send_error(s, m, "No such channel");
16022       return 0;
16023    }
16024    if (!analog_lib_handles(p->sig, 0, 0)) {
16025       astman_send_error(s, m, "Channel signaling is not analog");
16026       return 0;
16027    }
16028    dahdi_fake_event(p,TRANSFER);
16029    astman_send_ack(s, m, "DAHDITransfer");
16030    return 0;
16031 }

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

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

16034 {
16035    struct dahdi_pvt *p;
16036    const char *channel = astman_get_header(m, "DAHDIChannel");
16037 
16038    if (ast_strlen_zero(channel)) {
16039       astman_send_error(s, m, "No channel specified");
16040       return 0;
16041    }
16042    p = find_channel_from_str(channel);
16043    if (!p) {
16044       astman_send_error(s, m, "No such channel");
16045       return 0;
16046    }
16047    if (!analog_lib_handles(p->sig, 0, 0)) {
16048       astman_send_error(s, m, "Channel signaling is not analog");
16049       return 0;
16050    }
16051    dahdi_fake_event(p,HANGUP);
16052    astman_send_ack(s, m, "DAHDIHangup");
16053    return 0;
16054 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 4644 of file chan_dahdi.c.

References alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

04645 {
04646    int x;
04647    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04648       if (alarms[x].alarm & alm)
04649          return alarms[x].name;
04650    }
04651    return alm ? "Unknown Alarm" : "No Alarm";
04652 }

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

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

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

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

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

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

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

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

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

static int analog_tone_to_dahditone ( enum analog_tone  tone  )  [static]

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

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

static int analogsub_to_dahdisub ( enum analog_sub  analogsub  )  [static]

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

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

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

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

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

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

13257 {
13258    struct dahdi_pvt *p = *pvt;
13259 
13260    if (p->inalarm)
13261       return 0;
13262 
13263    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13264       return analog_available(p->sig_pvt);
13265 
13266    switch (p->sig) {
13267 #if defined(HAVE_PRI)
13268    case SIG_PRI_LIB_HANDLE_CASES:
13269       {
13270          struct sig_pri_chan *pvt_chan;
13271          int res;
13272 
13273          pvt_chan = p->sig_pvt;
13274          res = sig_pri_available(&pvt_chan, is_specific_channel);
13275          *pvt = pvt_chan->chan_pvt;
13276          return res;
13277       }
13278 #endif   /* defined(HAVE_PRI) */
13279 #if defined(HAVE_SS7)
13280    case SIG_SS7:
13281       return sig_ss7_available(p->sig_pvt);
13282 #endif   /* defined(HAVE_SS7) */
13283    default:
13284       break;
13285    }
13286 
13287    if (p->locallyblocked || p->remotelyblocked) {
13288       return 0;
13289    }
13290 
13291    /* If no owner definitely available */
13292    if (!p->owner) {
13293 #ifdef HAVE_OPENR2
13294       /* Trust MFC/R2 */
13295       if (p->mfcr2) {
13296          if (p->mfcr2call) {
13297             return 0;
13298          } else {
13299             return 1;
13300          }
13301       }
13302 #endif
13303       return 1;
13304    }
13305 
13306    return 0;
13307 }

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

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

16871 {
16872    char *c, *chan;
16873    char *subdir;
16874    int x, start, finish;
16875    struct dahdi_pvt *tmp;
16876 
16877    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16878       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16879       return -1;
16880    }
16881 
16882    c = ast_strdupa(value);
16883    c = parse_spanchan(c, &subdir);
16884 
16885    while ((chan = strsep(&c, ","))) {
16886       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16887          /* Range */
16888       } else if (sscanf(chan, "%30d", &start)) {
16889          /* Just one */
16890          finish = start;
16891       } else if (!strcasecmp(chan, "pseudo")) {
16892          finish = start = CHAN_PSEUDO;
16893          if (found_pseudo)
16894             *found_pseudo = 1;
16895       } else {
16896          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16897          return -1;
16898       }
16899       if (finish < start) {
16900          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16901          x = finish;
16902          finish = start;
16903          start = x;
16904       }
16905 
16906       for (x = start; x <= finish; x++) {
16907          char fn[PATH_MAX];
16908          int real_channel = x;
16909 
16910          if (!ast_strlen_zero(subdir)) {
16911             real_channel = device2chan(subdir, x, fn, sizeof(fn));
16912             if (real_channel < 0) {
16913                if (conf->ignore_failed_channels) {
16914                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16915                         subdir, x, real_channel);
16916                   continue;
16917                } else {
16918                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16919                         subdir, x, real_channel);
16920                   return -1;
16921                }
16922             }
16923          }
16924          tmp = mkintf(real_channel, conf, reload);
16925 
16926          if (tmp) {
16927             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16928          } else {
16929             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16930                   (reload == 1) ? "reconfigure" : "register", value);
16931             return -1;
16932          }
16933       }
16934    }
16935 
16936    return 0;
16937 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

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

05148 {
05149    int res;
05150 
05151    /* Bump receive gain by value stored in cid_rxgain */
05152    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05153    if (res) {
05154       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05155       return -1;
05156    }
05157 
05158    return 0;
05159 }

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

Definition at line 11104 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by do_monitor(), and mwi_thread().

11105 {
11106    int x;
11107    int sum = 0;
11108 
11109    if (!len)
11110       return 0;
11111 
11112    for (x = 0; x < len; x++)
11113       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11114 
11115    return sum / len;
11116 }

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

Definition at line 9926 of file chan_dahdi.c.

References ast_pickup_ext(), and pickup_ext.

Referenced by analog_ss_thread().

09927 {
09928    int extlen = strlen(exten);
09929    const char *pickup_ext;
09930    if (!extlen) {
09931       return 1;
09932    }
09933    pickup_ext = ast_pickup_ext();
09934    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09935       return 1;
09936    }
09937    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09938    if (exten[0] == '*' && extlen < 3) {
09939       if (extlen == 1) {
09940          return 1;
09941       }
09942       /* "*0" should be processed before it gets here */
09943       switch (exten[1]) {
09944       case '6':
09945       case '7':
09946       case '8':
09947          return 1;
09948       }
09949    }
09950    return 0;
09951 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

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

07721 {
07722    struct dahdi_confinfo ci;
07723    /* Fine if we already have a master, etc */
07724    if (p->master || (p->confno > -1))
07725       return 0;
07726    memset(&ci, 0, sizeof(ci));
07727    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07728       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07729       return 0;
07730    }
07731    /* If we have no master and don't have a confno, then
07732       if we're in a conference, it's probably a MeetMe room or
07733       some such, so don't let us 3-way out! */
07734    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07735       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07736       return 1;
07737    }
07738    return 0;
07739 }

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

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

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

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

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

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

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

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

09588 {
09589    struct ast_str *chan_name;
09590    int x, y;
09591 
09592    /* Create the new channel name tail. */
09593    if (!(chan_name = ast_str_create(32))) {
09594       return NULL;
09595    }
09596    if (i->channel == CHAN_PSEUDO) {
09597       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09598 #if defined(HAVE_PRI)
09599    } else if (i->pri) {
09600       ast_mutex_lock(&i->pri->lock);
09601       y = ++i->pri->new_chan_seq;
09602       if (is_outgoing) {
09603          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09604          address[0] = '\0';
09605       } else if (ast_strlen_zero(i->cid_subaddr)) {
09606          /* Put in caller-id number only since there is no subaddress. */
09607          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09608       } else {
09609          /* Put in caller-id number and subaddress. */
09610          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09611             i->cid_subaddr, y);
09612       }
09613       ast_mutex_unlock(&i->pri->lock);
09614 #endif   /* defined(HAVE_PRI) */
09615    } else {
09616       y = 1;
09617       do {
09618          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09619          for (x = 0; x < 3; ++x) {
09620             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09621                i->subs[x].owner->name + 6)) {
09622                break;
09623             }
09624          }
09625          ++y;
09626       } while (x < 3);
09627    }
09628    return chan_name;
09629 }

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

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

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

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

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

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

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

static int dahdi_callwait ( struct ast_channel ast  )  [static]

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

05349 {
05350    struct dahdi_pvt *p = ast->tech_pvt;
05351    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05352    if (p->cidspill) {
05353       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05354       ast_free(p->cidspill);
05355    }
05356 
05357    /*
05358     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05359     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05360     */
05361    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05362       return -1;
05363    save_conference(p);
05364    /* Silence */
05365    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05366    if (!p->callwaitrings && p->callwaitingcallerid) {
05367       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05368       p->callwaitcas = 1;
05369       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05370    } else {
05371       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05372       p->callwaitcas = 0;
05373       p->cidlen = 2400 + READ_SIZE * 4;
05374    }
05375    p->cidpos = 0;
05376    send_callerid(p);
05377 
05378    return 0;
05379 }

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

13922 {
13923    struct dahdi_pvt *p;
13924    struct dahdi_pvt *exitpvt;
13925    struct dahdi_starting_point start;
13926    int groupmatched = 0;
13927    int channelmatched = 0;
13928 
13929    ast_mutex_lock(&iflock);
13930    p = determine_starting_point(dest, &start);
13931    if (!p) {
13932       ast_mutex_unlock(&iflock);
13933       return -1;
13934    }
13935    exitpvt = p;
13936    for (;;) {
13937       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13938          /* We found a potential match. call the callback */
13939          struct ast_str *device_name;
13940          char *dash;
13941          const char *monitor_type;
13942          char dialstring[AST_CHANNEL_NAME];
13943          char full_device_name[AST_CHANNEL_NAME];
13944 
13945          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13946          case AST_CC_MONITOR_NEVER:
13947             break;
13948          case AST_CC_MONITOR_NATIVE:
13949          case AST_CC_MONITOR_ALWAYS:
13950          case AST_CC_MONITOR_GENERIC:
13951 #if defined(HAVE_PRI)
13952             if (dahdi_sig_pri_lib_handles(p->sig)) {
13953                /*
13954                 * ISDN is in a trunk busy condition so we need to monitor
13955                 * the span congestion device state.
13956                 */
13957                snprintf(full_device_name, sizeof(full_device_name),
13958                   "DAHDI/I%d/congestion", p->pri->span);
13959             } else
13960 #endif   /* defined(HAVE_PRI) */
13961             {
13962 #if defined(HAVE_PRI)
13963                device_name = create_channel_name(p, 1, "");
13964 #else
13965                device_name = create_channel_name(p);
13966 #endif   /* defined(HAVE_PRI) */
13967                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13968                   device_name ? ast_str_buffer(device_name) : "");
13969                ast_free(device_name);
13970                /*
13971                 * The portion after the '-' in the channel name is either a random
13972                 * number, a sequence number, or a subchannel number. None are
13973                 * necessary so strip them off.
13974                 */
13975                dash = strrchr(full_device_name, '-');
13976                if (dash) {
13977                   *dash = '\0';
13978                }
13979             }
13980             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13981 
13982             /*
13983              * Analog can only do generic monitoring.
13984              * ISDN is in a trunk busy condition and any "device" is going
13985              * to be busy until a B channel becomes available.  The generic
13986              * monitor can do this task.
13987              */
13988             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13989             callback(inbound,
13990 #if defined(HAVE_PRI)
13991                p->pri ? p->pri->cc_params : p->cc_params,
13992 #else
13993                p->cc_params,
13994 #endif   /* defined(HAVE_PRI) */
13995                monitor_type, full_device_name, dialstring, NULL);
13996             break;
13997          }
13998       }
13999       p = start.backwards ? p->prev : p->next;
14000       if (!p) {
14001          p = start.backwards ? ifend : iflist;
14002       }
14003       if (p == exitpvt) {
14004          break;
14005       }
14006    }
14007    ast_mutex_unlock(&iflock);
14008    return 0;
14009 }

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

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

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

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

18532 {
18533    struct dahdi_pvt *tmp;
18534    struct ast_data *data_channel;
18535 
18536    ast_mutex_lock(&iflock);
18537    for (tmp = iflist; tmp; tmp = tmp->next) {
18538       data_channel = ast_data_add_node(data_root, "channel");
18539       if (!data_channel) {
18540          continue;
18541       }
18542 
18543       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18544 
18545       /* if this channel doesn't match remove it. */
18546       if (!ast_data_search_match(search, data_channel)) {
18547          ast_data_remove_node(data_root, data_channel);
18548       }
18549    }
18550    ast_mutex_unlock(&iflock);
18551 
18552    return 0;
18553 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 4411 of file chan_dahdi.c.

Referenced by dahdi_close_sub().

04412 {
04413    if (fd > 0)
04414       close(fd);
04415 }

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

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

04418 {
04419    dahdi_close(chan_pvt->subs[sub_num].dfd);
04420    chan_pvt->subs[sub_num].dfd = -1;
04421 }

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

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

05192 {
05193    int x, res;
05194 
05195    x = muted;
05196 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05197    switch (p->sig) {
05198 #if defined(HAVE_PRI)
05199    case SIG_PRI_LIB_HANDLE_CASES:
05200       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05201          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05202          break;
05203       }
05204       /* Fall through */
05205 #endif   /* defined(HAVE_PRI) */
05206 #if defined(HAVE_SS7)
05207    case SIG_SS7:
05208 #endif   /* defined(HAVE_SS7) */
05209       {
05210          int y = 1;
05211 
05212          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05213          if (res)
05214             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05215                p->channel, strerror(errno));
05216       }
05217       break;
05218    default:
05219       break;
05220    }
05221 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05222    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05223    if (res < 0)
05224       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05225    return res;
05226 }

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

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

15070 {
15071    int channel;
15072    int ret;
15073    switch (cmd) {
15074    case CLI_INIT:
15075       e->command = "dahdi destroy channel";
15076       e->usage =
15077          "Usage: dahdi destroy channel <chan num>\n"
15078          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15079       return NULL;
15080    case CLI_GENERATE:
15081       return NULL;
15082    }
15083    if (a->argc != 4)
15084       return CLI_SHOWUSAGE;
15085 
15086    channel = atoi(a->argv[3]);
15087    ret = dahdi_destroy_channel_bynum(channel);
15088    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15089 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

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

11455 {
11456    struct dahdi_pvt *cur;
11457 
11458    ast_mutex_lock(&iflock);
11459    for (cur = iflist; cur; cur = cur->next) {
11460       if (cur->channel == channel) {
11461          int x = DAHDI_FLASH;
11462 
11463          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11464          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11465 
11466          destroy_channel(cur, 1);
11467          ast_mutex_unlock(&iflock);
11468          ast_module_unref(ast_module_info->self);
11469          return RESULT_SUCCESS;
11470       }
11471    }
11472    ast_mutex_unlock(&iflock);
11473    return RESULT_FAILURE;
11474 }

static int dahdi_devicestate ( void *  data  )  [static]

Definition at line 13859 of file chan_dahdi.c.

References AST_DEVICE_UNKNOWN.

13860 {
13861 #if defined(HAVE_PRI)
13862    char *device;
13863    unsigned span;
13864    int res;
13865 
13866    device = data;
13867 
13868    if (*device != 'I') {
13869       /* The request is not for an ISDN span device. */
13870       return AST_DEVICE_UNKNOWN;
13871    }
13872    res = sscanf(device, "I%30u", &span);
13873    if (res != 1 || !span || NUM_SPANS < span) {
13874       /* Bad format for ISDN span device name. */
13875       return AST_DEVICE_UNKNOWN;
13876    }
13877    device = strchr(device, '/');
13878    if (!device) {
13879       /* Bad format for ISDN span device name. */
13880       return AST_DEVICE_UNKNOWN;
13881    }
13882 
13883    /*
13884     * Since there are currently no other span devstate's defined,
13885     * it must be congestion.
13886     */
13887 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13888    ++device;
13889    if (!strcmp(device, "congestion"))
13890 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13891    {
13892       return pris[span - 1].pri.congestion_devstate;
13893    }
13894 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13895    else if (!strcmp(device, "threshold")) {
13896       return pris[span - 1].pri.threshold_devstate;
13897    }
13898    return AST_DEVICE_UNKNOWN;
13899 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13900 #else
13901    return AST_DEVICE_UNKNOWN;
13902 #endif   /* defined(HAVE_PRI) */
13903 }

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

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

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

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

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

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

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

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

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

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

09904 {
09905    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09906       return analog_dnd(dahdichan->sig_pvt, flag);
09907    }
09908 
09909    if (flag == -1) {
09910       return dahdichan->dnd;
09911    }
09912 
09913    /* Do not disturb */
09914    dahdichan->dnd = flag;
09915    ast_verb(3, "%s DND on channel %d\n",
09916          flag? "Enabled" : "Disabled",
09917          dahdichan->channel);
09918    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09919          "Channel: DAHDI/%d\r\n"
09920          "Status: %s\r\n", dahdichan->channel,
09921          flag? "enabled" : "disabled");
09922 
09923    return 0;
09924 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

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

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

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

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

08925 {
08926    struct dahdi_pvt *p = ast->tech_pvt;
08927    struct ast_frame *f;
08928    ast_mutex_lock(&p->lock);
08929    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08930       struct analog_pvt *analog_p = p->sig_pvt;
08931       f = analog_exception(analog_p, ast);
08932    } else {
08933       f = __dahdi_exception(ast);
08934    }
08935    ast_mutex_unlock(&p->lock);
08936    return f;
08937 }

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

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

15922 {
15923    if (p) {
15924       switch (mode) {
15925       case TRANSFER:
15926          p->fake_event = DAHDI_EVENT_WINKFLASH;
15927          break;
15928       case HANGUP:
15929          p->fake_event = DAHDI_EVENT_ONHOOK;
15930          break;
15931       default:
15932          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15933       }
15934    }
15935    return 0;
15936 }

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

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

07597 {
07598    struct dahdi_pvt *p = newchan->tech_pvt;
07599    int x;
07600 
07601    ast_mutex_lock(&p->lock);
07602 
07603    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07604    if (p->owner == oldchan) {
07605       p->owner = newchan;
07606    }
07607    for (x = 0; x < 3; x++) {
07608       if (p->subs[x].owner == oldchan) {
07609          if (!x) {
07610             dahdi_unlink(NULL, p, 0);
07611          }
07612          p->subs[x].owner = newchan;
07613       }
07614    }
07615    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07616       analog_fixup(oldchan, newchan, p->sig_pvt);
07617 #if defined(HAVE_PRI)
07618    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07619       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07620 #endif   /* defined(HAVE_PRI) */
07621 #if defined(HAVE_SS7)
07622    } else if (p->sig == SIG_SS7) {
07623       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07624 #endif   /* defined(HAVE_SS7) */
07625    }
07626    update_conf(p);
07627 
07628    ast_mutex_unlock(&p->lock);
07629 
07630    if (newchan->_state == AST_STATE_RINGING) {
07631       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07632    }
07633    return 0;
07634 }

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

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

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

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

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

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

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

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

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

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

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

static int dahdi_hangup ( struct ast_channel ast  )  [static]

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

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

static void dahdi_iflist_extract ( struct dahdi_pvt pvt  )  [static]

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

05568 {
05569    /* Extract from the forward chain. */
05570    if (pvt->prev) {
05571       pvt->prev->next = pvt->next;
05572    } else if (iflist == pvt) {
05573       /* Node is at the head of the list. */
05574       iflist = pvt->next;
05575    }
05576 
05577    /* Extract from the reverse chain. */
05578    if (pvt->next) {
05579       pvt->next->prev = pvt->prev;
05580    } else if (ifend == pvt) {
05581       /* Node is at the end of the list. */
05582       ifend = pvt->prev;
05583    }
05584 
05585    /* Node is no longer in the list. */
05586    pvt->which_iflist = DAHDI_IFLIST_NONE;
05587    pvt->prev = NULL;
05588    pvt->next = NULL;
05589 }

static void dahdi_iflist_insert ( struct dahdi_pvt pvt  )  [static]

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

05518 {
05519    struct dahdi_pvt *cur;
05520 
05521    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05522 
05523    /* Find place in middle of list for the new interface. */
05524    for (cur = iflist; cur; cur = cur->next) {
05525       if (pvt->channel < cur->channel) {
05526          /* New interface goes before the current interface. */
05527          pvt->prev = cur->prev;
05528          pvt->next = cur;
05529          if (cur->prev) {
05530             /* Insert into the middle of the list. */
05531             cur->prev->next = pvt;
05532          } else {
05533             /* Insert at head of list. */
05534             iflist = pvt;
05535          }
05536          cur->prev = pvt;
05537          return;
05538       }
05539    }
05540 
05541    /* New interface goes onto the end of the list */
05542    pvt->prev = ifend;
05543    pvt->next = NULL;
05544    if (ifend) {
05545       ifend->next = pvt;
05546    }
05547    ifend = pvt;
05548    if (!iflist) {
05549       /* List was empty */
05550       iflist = pvt;
05551    }
05552 }

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

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

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

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

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

07220                                                                           {
07221    int x;
07222    if (!slave || !master) {
07223       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07224       return;
07225    }
07226    for (x = 0; x < MAX_SLAVES; x++) {
07227       if (!master->slaves[x]) {
07228          master->slaves[x] = slave;
07229          break;
07230       }
07231    }
07232    if (x >= MAX_SLAVES) {
07233       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07234       master->slaves[MAX_SLAVES - 1] = slave;
07235    }
07236    if (slave->master)
07237       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07238    slave->master = master;
07239 
07240    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07241 }

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

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

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

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

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

static int dahdi_open ( char *  fn  )  [static]

Definition at line 4364 of file chan_dahdi.c.

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

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

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

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

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

06692 {
06693    char *cp;
06694    struct dahdi_pvt *p = chan->tech_pvt;
06695 
06696    /* all supported options require data */
06697    if (!p || !data || (*datalen < 1)) {
06698       errno = EINVAL;
06699       return -1;
06700    }
06701 
06702    switch (option) {
06703    case AST_OPTION_DIGIT_DETECT:
06704       cp = (char *) data;
06705       *cp = p->ignoredtmf ? 0 : 1;
06706       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06707       break;
06708    case AST_OPTION_FAX_DETECT:
06709       cp = (char *) data;
06710       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06711       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06712       break;
06713    case AST_OPTION_CC_AGENT_TYPE:
06714 #if defined(HAVE_PRI)
06715 #if defined(HAVE_PRI_CCSS)
06716       if (dahdi_sig_pri_lib_handles(p->sig)) {
06717          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06718          break;
06719       }
06720 #endif   /* defined(HAVE_PRI_CCSS) */
06721 #endif   /* defined(HAVE_PRI) */
06722       return -1;
06723    default:
06724       return -1;
06725    }
06726 
06727    errno = 0;
06728 
06729    return 0;
06730 }

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

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

03853 {
03854    for (;;) {
03855       if (p->owner) {
03856          if (ast_channel_trylock(p->owner)) {
03857             DEADLOCK_AVOIDANCE(&p->lock);
03858          } else {
03859             ast_queue_frame(p->owner, f);
03860             ast_channel_unlock(p->owner);
03861             break;
03862          }
03863       } else
03864          break;
03865    }
03866 }

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

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

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

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

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

static int dahdi_restart ( void   )  [static]

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

15121 {
15122 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15123    int i, j;
15124 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15125    int cancel_code;
15126    struct dahdi_pvt *p;
15127 
15128    ast_mutex_lock(&restart_lock);
15129    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15130    dahdi_softhangup_all();
15131    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15132 #ifdef HAVE_OPENR2
15133    dahdi_r2_destroy_links();
15134 #endif
15135 
15136 #if defined(HAVE_PRI)
15137    for (i = 0; i < NUM_SPANS; i++) {
15138       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15139          cancel_code = pthread_cancel(pris[i].pri.master);
15140          pthread_kill(pris[i].pri.master, SIGURG);
15141          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);
15142          pthread_join(pris[i].pri.master, NULL);
15143          ast_debug(4, "Joined thread of span %d\n", i);
15144       }
15145    }
15146 #endif
15147 
15148 #if defined(HAVE_SS7)
15149    for (i = 0; i < NUM_SPANS; i++) {
15150       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15151          cancel_code = pthread_cancel(linksets[i].ss7.master);
15152          pthread_kill(linksets[i].ss7.master, SIGURG);
15153          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);
15154          pthread_join(linksets[i].ss7.master, NULL);
15155          ast_debug(4, "Joined thread of span %d\n", i);
15156       }
15157    }
15158 #endif   /* defined(HAVE_SS7) */
15159 
15160    ast_mutex_lock(&monlock);
15161    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15162       cancel_code = pthread_cancel(monitor_thread);
15163       pthread_kill(monitor_thread, SIGURG);
15164       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15165       pthread_join(monitor_thread, NULL);
15166       ast_debug(4, "Joined monitor thread\n");
15167    }
15168    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15169 
15170    ast_mutex_lock(&ss_thread_lock);
15171    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15172       int x = DAHDI_FLASH;
15173       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15174 
15175       ast_mutex_lock(&iflock);
15176       for (p = iflist; p; p = p->next) {
15177          if (p->owner) {
15178             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15179             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15180          }
15181       }
15182       ast_mutex_unlock(&iflock);
15183       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15184    }
15185 
15186    /* ensure any created channels before monitor threads were stopped are hungup */
15187    dahdi_softhangup_all();
15188    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15189    destroy_all_channels();
15190    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15191 
15192    ast_mutex_unlock(&monlock);
15193 
15194 #ifdef HAVE_PRI
15195    for (i = 0; i < NUM_SPANS; i++) {
15196       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15197          dahdi_close_pri_fd(&(pris[i]), j);
15198    }
15199 
15200    memset(pris, 0, sizeof(pris));
15201    for (i = 0; i < NUM_SPANS; i++) {
15202       sig_pri_init_pri(&pris[i].pri);
15203    }
15204    pri_set_error(dahdi_pri_error);
15205    pri_set_message(dahdi_pri_message);
15206 #endif
15207 #if defined(HAVE_SS7)
15208    for (i = 0; i < NUM_SPANS; i++) {
15209       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15210          dahdi_close_ss7_fd(&(linksets[i]), j);
15211    }
15212 
15213    memset(linksets, 0, sizeof(linksets));
15214    for (i = 0; i < NUM_SPANS; i++) {
15215       sig_ss7_init_linkset(&linksets[i].ss7);
15216    }
15217    ss7_set_error(dahdi_ss7_error);
15218    ss7_set_message(dahdi_ss7_message);
15219 #endif   /* defined(HAVE_SS7) */
15220 
15221    if (setup_dahdi(2) != 0) {
15222       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15223       ast_mutex_unlock(&ss_thread_lock);
15224       return 1;
15225    }
15226    ast_mutex_unlock(&ss_thread_lock);
15227    ast_mutex_unlock(&restart_lock);
15228    return 0;
15229 }

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

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

15232 {
15233    switch (cmd) {
15234    case CLI_INIT:
15235       e->command = "dahdi restart";
15236       e->usage =
15237          "Usage: dahdi restart\n"
15238          "  Restarts the DAHDI channels: destroys them all and then\n"
15239          "  re-reads them from chan_dahdi.conf.\n"
15240          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15241          "";
15242       return NULL;
15243    case CLI_GENERATE:
15244       return NULL;
15245    }
15246    if (a->argc != 2)
15247       return CLI_SHOWUSAGE;
15248 
15249    if (dahdi_restart() != 0)
15250       return CLI_FAILURE;
15251    return CLI_SUCCESS;
15252 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

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

07637 {
07638    int x;
07639    int res;
07640    /* Make sure our transmit state is on hook */
07641    x = 0;
07642    x = DAHDI_ONHOOK;
07643    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07644    do {
07645       x = DAHDI_RING;
07646       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07647       if (res) {
07648          switch (errno) {
07649          case EBUSY:
07650          case EINTR:
07651             /* Wait just in case */
07652             usleep(10000);
07653             continue;
07654          case EINPROGRESS:
07655             res = 0;
07656             break;
07657          default:
07658             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07659             res = 0;
07660          }
07661       }
07662    } while (res);
07663    return res;
07664 }

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

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

18691 {
18692 #define  END_SILENCE_LEN 400
18693 #define  HEADER_MS 50
18694 #define  TRAILER_MS 5
18695 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18696 #define  ASCII_BYTES_PER_CHAR 80
18697 
18698    unsigned char *buf,*mybuf;
18699    struct dahdi_pvt *p = c->tech_pvt;
18700    struct pollfd fds[1];
18701    int size,res,fd,len,x;
18702    int bytes=0;
18703    /* Initial carrier (imaginary) */
18704    float cr = 1.0;
18705    float ci = 0.0;
18706    float scont = 0.0;
18707    int idx;
18708 
18709    idx = dahdi_get_index(c, p, 0);
18710    if (idx < 0) {
18711       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18712       return -1;
18713    }
18714    if (!text[0]) return(0); /* if nothing to send, don't */
18715    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18716    if (p->mate)
18717       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18718    else
18719       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18720    if (!buf)
18721       return -1;
18722    mybuf = buf;
18723    if (p->mate) {
18724       int codec = AST_LAW(p);
18725       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18726          PUT_CLID_MARKMS;
18727       }
18728       /* Put actual message */
18729       for (x = 0; text[x]; x++) {
18730          PUT_CLID(text[x]);
18731       }
18732       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18733          PUT_CLID_MARKMS;
18734       }
18735       len = bytes;
18736       buf = mybuf;
18737    } else {
18738       len = tdd_generate(p->tdd, buf, text);
18739       if (len < 1) {
18740          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18741          ast_free(mybuf);
18742          return -1;
18743       }
18744    }
18745    memset(buf + len, 0x7f, END_SILENCE_LEN);
18746    len += END_SILENCE_LEN;
18747    fd = p->subs[idx].dfd;
18748    while (len) {
18749       if (ast_check_hangup(c)) {
18750          ast_free(mybuf);
18751          return -1;
18752       }
18753       size = len;
18754       if (size > READ_SIZE)
18755          size = READ_SIZE;
18756       fds[0].fd = fd;
18757       fds[0].events = POLLOUT | POLLPRI;
18758       fds[0].revents = 0;
18759       res = poll(fds, 1, -1);
18760       if (!res) {
18761          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18762          continue;
18763       }
18764       /* if got exception */
18765       if (fds[0].revents & POLLPRI) {
18766          ast_free(mybuf);
18767          return -1;
18768       }
18769       if (!(fds[0].revents & POLLOUT)) {
18770          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18771          continue;
18772       }
18773       res = write(fd, buf, size);
18774       if (res != size) {
18775          if (res == -1) {
18776             ast_free(mybuf);
18777             return -1;
18778          }
18779          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18780          break;
18781       }
18782       len -= size;
18783       buf += size;
18784    }
18785    ast_free(mybuf);
18786    return(0);
18787 }

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

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

15849 {
15850    int channel;
15851    int on;
15852    struct dahdi_pvt *dahdi_chan = NULL;
15853 
15854    switch (cmd) {
15855    case CLI_INIT:
15856       e->command = "dahdi set dnd";
15857       e->usage =
15858          "Usage: dahdi set dnd <chan#> <on|off>\n"
15859          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15860          "  Changes take effect immediately.\n"
15861          "  <chan num> is the channel number\n"
15862          "  <on|off> Enable or disable DND mode?\n"
15863          ;
15864       return NULL;
15865    case CLI_GENERATE:
15866       return NULL;
15867    }
15868 
15869    if (a->argc != 5)
15870       return CLI_SHOWUSAGE;
15871 
15872    if ((channel = atoi(a->argv[3])) <= 0) {
15873       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15874       return CLI_SHOWUSAGE;
15875    }
15876 
15877    if (ast_true(a->argv[4]))
15878       on = 1;
15879    else if (ast_false(a->argv[4]))
15880       on = 0;
15881    else {
15882       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15883       return CLI_SHOWUSAGE;
15884    }
15885 
15886    ast_mutex_lock(&iflock);
15887    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15888       if (dahdi_chan->channel != channel)
15889          continue;
15890 
15891       /* Found the channel. Actually set it */
15892       dahdi_dnd(dahdi_chan, on);
15893       break;
15894    }
15895    ast_mutex_unlock(&iflock);
15896 
15897    if (!dahdi_chan) {
15898       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15899       return CLI_FAILURE;
15900    }
15901 
15902    return CLI_SUCCESS;
15903 }

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

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

05175 {
05176    int x, res;
05177 
05178    x = hs;
05179    res = ioctl(fd, DAHDI_HOOK, &x);
05180 
05181    if (res < 0) {
05182       if (errno == EINPROGRESS)
05183          return 0;
05184       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05185       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05186    }
05187 
05188    return res;
05189 }

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

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

15709 {
15710    int channel;
15711    int gain;
15712    int tx;
15713    struct dahdi_hwgain hwgain;
15714    struct dahdi_pvt *tmp = NULL;
15715 
15716    switch (cmd) {
15717    case CLI_INIT:
15718       e->command = "dahdi set hwgain";
15719       e->usage =
15720          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15721          "  Sets the hardware gain on a a given channel, overriding the\n"
15722          "   value provided at module loadtime, whether the channel is in\n"
15723          "   use or not.  Changes take effect immediately.\n"
15724          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15725          "   <chan num> is the channel number relative to the device\n"
15726          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15727       return NULL;
15728    case CLI_GENERATE:
15729       return NULL;
15730    }
15731 
15732    if (a->argc != 6)
15733       return CLI_SHOWUSAGE;
15734 
15735    if (!strcasecmp("rx", a->argv[3]))
15736       tx = 0; /* rx */
15737    else if (!strcasecmp("tx", a->argv[3]))
15738       tx = 1; /* tx */
15739    else
15740       return CLI_SHOWUSAGE;
15741 
15742    channel = atoi(a->argv[4]);
15743    gain = atof(a->argv[5])*10.0;
15744 
15745    ast_mutex_lock(&iflock);
15746 
15747    for (tmp = iflist; tmp; tmp = tmp->next) {
15748 
15749       if (tmp->channel != channel)
15750          continue;
15751 
15752       if (tmp->subs[SUB_REAL].dfd == -1)
15753          break;
15754 
15755       hwgain.newgain = gain;
15756       hwgain.tx = tx;
15757       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15758          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15759          ast_mutex_unlock(&iflock);
15760          return CLI_FAILURE;
15761       }
15762       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15763          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15764       break;
15765    }
15766 
15767    ast_mutex_unlock(&iflock);
15768 
15769    if (tmp)
15770       return CLI_SUCCESS;
15771 
15772    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15773    return CLI_FAILURE;
15774 
15775 }

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

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

15778 {
15779    int channel;
15780    float gain;
15781    int tx;
15782    int res;
15783    struct dahdi_pvt *tmp = NULL;
15784 
15785    switch (cmd) {
15786    case CLI_INIT:
15787       e->command = "dahdi set swgain";
15788       e->usage =
15789          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15790          "  Sets the software gain on a a given channel, overriding the\n"
15791          "   value provided at module loadtime, whether the channel is in\n"
15792          "   use or not.  Changes take effect immediately.\n"
15793          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15794          "   <chan num> is the channel number relative to the device\n"
15795          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15796       return NULL;
15797    case CLI_GENERATE:
15798       return NULL;
15799    }
15800 
15801    if (a->argc != 6)
15802       return CLI_SHOWUSAGE;
15803 
15804    if (!strcasecmp("rx", a->argv[3]))
15805       tx = 0; /* rx */
15806    else if (!strcasecmp("tx", a->argv[3]))
15807       tx = 1; /* tx */
15808    else
15809       return CLI_SHOWUSAGE;
15810 
15811    channel = atoi(a->argv[4]);
15812    gain = atof(a->argv[5]);
15813 
15814    ast_mutex_lock(&iflock);
15815    for (tmp = iflist; tmp; tmp = tmp->next) {
15816 
15817       if (tmp->channel != channel)
15818          continue;
15819 
15820       if (tmp->subs[SUB_REAL].dfd == -1)
15821          break;
15822 
15823       if (tx)
15824          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15825       else
15826          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15827 
15828       if (res) {
15829          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15830          ast_mutex_unlock(&iflock);
15831          return CLI_FAILURE;
15832       }
15833 
15834       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15835          tx ? "tx" : "rx", gain, channel);
15836       break;
15837    }
15838    ast_mutex_unlock(&iflock);
15839 
15840    if (tmp)
15841       return CLI_SUCCESS;
15842 
15843    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15844    return CLI_FAILURE;
15845 
15846 }

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

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

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

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

15352 {
15353    int channel;
15354    struct dahdi_pvt *tmp = NULL;
15355    struct dahdi_confinfo ci;
15356    struct dahdi_params ps;
15357    int x;
15358 
15359    switch (cmd) {
15360    case CLI_INIT:
15361       e->command = "dahdi show channel";
15362       e->usage =
15363          "Usage: dahdi show channel <chan num>\n"
15364          "  Detailed information about a given channel\n";
15365       return NULL;
15366    case CLI_GENERATE:
15367       return NULL;
15368    }
15369 
15370    if (a->argc != 4)
15371       return CLI_SHOWUSAGE;
15372 
15373    channel = atoi(a->argv[3]);
15374 
15375    ast_mutex_lock(&iflock);
15376    for (tmp = iflist; tmp; tmp = tmp->next) {
15377       if (tmp->channel == channel) {
15378          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15379          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15380          ast_cli(a->fd, "Span: %d\n", tmp->span);
15381          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15382          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15383          ast_cli(a->fd, "Context: %s\n", tmp->context);
15384          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15385          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15386 #if defined(HAVE_PRI)
15387 #if defined(HAVE_PRI_SUBADDR)
15388          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15389 #endif   /* defined(HAVE_PRI_SUBADDR) */
15390 #endif   /* defined(HAVE_PRI) */
15391          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15392          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15393          if (tmp->vars) {
15394             struct ast_variable *v;
15395             ast_cli(a->fd, "Variables:\n");
15396             for (v = tmp->vars ; v ; v = v->next)
15397                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15398          }
15399          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15400          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15401          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15402          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15403          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15404          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)" : "");
15405          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)" : "");
15406          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)" : "");
15407          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15408          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15409          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15410          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15411          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15412          if (tmp->busydetect) {
15413 #if defined(BUSYDETECT_TONEONLY)
15414             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15415 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15416             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15417 #endif
15418 #ifdef BUSYDETECT_DEBUG
15419             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15420 #endif
15421             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15422             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
15423          }
15424          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15425          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15426          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15427          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15428          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15429          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15430          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15431          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15432          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15433          ast_cli(a->fd, "Echo Cancellation:\n");
15434 
15435          if (tmp->echocancel.head.tap_length) {
15436             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15437             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15438                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15439             }
15440             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15441          } else {
15442             ast_cli(a->fd, "\tnone\n");
15443          }
15444          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15445          if (tmp->master)
15446             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15447          for (x = 0; x < MAX_SLAVES; x++) {
15448             if (tmp->slaves[x])
15449                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15450          }
15451 #ifdef HAVE_OPENR2
15452          if (tmp->mfcr2) {
15453             char calldir[OR2_MAX_PATH];
15454             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15455             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15456             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15457             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15458             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15459             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15460             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15461             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15462             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15463             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15464             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15465 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15466             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15467 #endif
15468             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15469             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15470             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15471             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15472             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15473             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15474             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15475             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15476             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15477             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15478             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15479             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15480          }
15481 #endif
15482 #if defined(HAVE_SS7)
15483          if (tmp->ss7) {
15484             struct sig_ss7_chan *chan = tmp->sig_pvt;
15485 
15486             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15487          }
15488 #endif   /* defined(HAVE_SS7) */
15489 #ifdef HAVE_PRI
15490          if (tmp->pri) {
15491             struct sig_pri_chan *chan = tmp->sig_pvt;
15492 
15493             ast_cli(a->fd, "PRI Flags: ");
15494             if (chan->resetting != SIG_PRI_RESET_IDLE) {
15495                ast_cli(a->fd, "Resetting=%d ", chan->resetting);
15496             }
15497             if (chan->call)
15498                ast_cli(a->fd, "Call ");
15499             if (chan->allocated) {
15500                ast_cli(a->fd, "Allocated ");
15501             }
15502             ast_cli(a->fd, "\n");
15503             if (tmp->logicalspan)
15504                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15505             else
15506                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15507          }
15508 #endif
15509          memset(&ci, 0, sizeof(ci));
15510          ps.channo = tmp->channel;
15511          if (tmp->subs[SUB_REAL].dfd > -1) {
15512             memset(&ci, 0, sizeof(ci));
15513             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15514                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15515             }
15516             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15517                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15518             }
15519             memset(&ps, 0, sizeof(ps));
15520             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15521                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15522             } else {
15523                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15524             }
15525          }
15526          if (ISTRUNK(tmp)) {
15527             ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
15528             if (!ast_strlen_zero(progzone))
15529                ast_cli(a->fd, "Progress Zone: %s\n", progzone);
15530             ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
15531             if(tmp->busydetect) {
15532                ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
15533                if(tmp->busytonelength > 0) {
15534                   ast_cli(a->fd, "Busy Pattern:\n");
15535                   ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
15536                   if (tmp->busyquietlength > 0) 
15537                      ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
15538                   else 
15539                      ast_cli(a->fd, " -- Detect Tone Only\n");
15540                   if(tmp->busyfuzziness > 0)
15541                      ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
15542                }
15543             }
15544          }
15545          ast_mutex_unlock(&iflock);
15546          return CLI_SUCCESS;
15547       }
15548    }
15549    ast_mutex_unlock(&iflock);
15550 
15551    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15552    return CLI_FAILURE;
15553 }

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

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

15265 {
15266 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15267 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15268    ast_group_t targetnum = 0;
15269    int filtertype = 0;
15270    struct dahdi_pvt *tmp = NULL;
15271    char tmps[20] = "";
15272    char statestr[20] = "";
15273    char blockstr[20] = "";
15274 
15275    switch (cmd) {
15276    case CLI_INIT:
15277       e->command = "dahdi show channels [group|context]";
15278       e->usage =
15279          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15280          "  Shows a list of available channels with optional filtering\n"
15281          "  <group> must be a number between 0 and 63\n";
15282       return NULL;
15283    case CLI_GENERATE:
15284       return NULL;
15285    }
15286 
15287    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15288 
15289    if (!((a->argc == 3) || (a->argc == 5)))
15290       return CLI_SHOWUSAGE;
15291 
15292    if (a->argc == 5) {
15293       if (!strcasecmp(a->argv[3], "group")) {
15294          targetnum = atoi(a->argv[4]);
15295          if (63 < targetnum) {
15296             return CLI_SHOWUSAGE;
15297          }
15298          targetnum = ((ast_group_t) 1) << targetnum;
15299          filtertype = 1;
15300       } else if (!strcasecmp(a->argv[3], "context")) {
15301          filtertype = 2;
15302       }
15303    }
15304 
15305    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15306    ast_mutex_lock(&iflock);
15307    for (tmp = iflist; tmp; tmp = tmp->next) {
15308       if (filtertype) {
15309          switch(filtertype) {
15310          case 1: /* dahdi show channels group <group> */
15311             if (!(tmp->group & targetnum)) {
15312                continue;
15313             }
15314             break;
15315          case 2: /* dahdi show channels context <context> */
15316             if (strcasecmp(tmp->context, a->argv[4])) {
15317                continue;
15318             }
15319             break;
15320          default:
15321             break;
15322          }
15323       }
15324       if (tmp->channel > 0) {
15325          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15326       } else
15327          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15328 
15329       if (tmp->locallyblocked)
15330          blockstr[0] = 'L';
15331       else
15332          blockstr[0] = ' ';
15333 
15334       if (tmp->remotelyblocked)
15335          blockstr[1] = 'R';
15336       else
15337          blockstr[1] = ' ';
15338 
15339       blockstr[2] = '\0';
15340 
15341       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15342 
15343       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15344    }
15345    ast_mutex_unlock(&iflock);
15346    return CLI_SUCCESS;
15347 #undef FORMAT
15348 #undef FORMAT2
15349 }

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

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

15593 {
15594    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15595    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15596    int span;
15597    int res;
15598    char alarmstr[50];
15599 
15600    int ctl;
15601    struct dahdi_spaninfo s;
15602 
15603    switch (cmd) {
15604    case CLI_INIT:
15605       e->command = "dahdi show status";
15606       e->usage =
15607          "Usage: dahdi show status\n"
15608          "       Shows a list of DAHDI cards with status\n";
15609       return NULL;
15610    case CLI_GENERATE:
15611       return NULL;
15612    }
15613    ctl = open("/dev/dahdi/ctl", O_RDWR);
15614    if (ctl < 0) {
15615       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15616       return CLI_FAILURE;
15617    }
15618    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15619 
15620    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15621       s.spanno = span;
15622       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15623       if (res) {
15624          continue;
15625       }
15626       alarmstr[0] = '\0';
15627       if (s.alarms > 0) {
15628          if (s.alarms & DAHDI_ALARM_BLUE)
15629             strcat(alarmstr, "BLU/");
15630          if (s.alarms & DAHDI_ALARM_YELLOW)
15631             strcat(alarmstr, "YEL/");
15632          if (s.alarms & DAHDI_ALARM_RED)
15633             strcat(alarmstr, "RED/");
15634          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15635             strcat(alarmstr, "LB/");
15636          if (s.alarms & DAHDI_ALARM_RECOVER)
15637             strcat(alarmstr, "REC/");
15638          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15639             strcat(alarmstr, "NOP/");
15640          if (!strlen(alarmstr))
15641             strcat(alarmstr, "UUU/");
15642          if (strlen(alarmstr)) {
15643             /* Strip trailing / */
15644             alarmstr[strlen(alarmstr) - 1] = '\0';
15645          }
15646       } else {
15647          if (s.numchans)
15648             strcpy(alarmstr, "OK");
15649          else
15650             strcpy(alarmstr, "UNCONFIGURED");
15651       }
15652 
15653       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15654          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15655          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15656          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15657          "CAS",
15658          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15659          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15660          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15661          "Unk",
15662          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15663             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15664             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15665          lbostr[s.lbo]
15666          );
15667    }
15668    close(ctl);
15669 
15670    return CLI_SUCCESS;
15671 #undef FORMAT
15672 #undef FORMAT2
15673 }

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

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

15676 {
15677    int pseudo_fd = -1;
15678    struct dahdi_versioninfo vi;
15679 
15680    switch (cmd) {
15681    case CLI_INIT:
15682       e->command = "dahdi show version";
15683       e->usage =
15684          "Usage: dahdi show version\n"
15685          "       Shows the DAHDI version in use\n";
15686       return NULL;
15687    case CLI_GENERATE:
15688       return NULL;
15689    }
15690    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15691       ast_cli(a->fd, "Failed to open control file to get version.\n");
15692       return CLI_SUCCESS;
15693    }
15694 
15695    strcpy(vi.version, "Unknown");
15696    strcpy(vi.echo_canceller, "Unknown");
15697 
15698    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15699       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15700    else
15701       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15702 
15703    close(pseudo_fd);
15704 
15705    return CLI_SUCCESS;
15706 }

static char* dahdi_sig2str ( int  sig  )  [static]

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

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

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

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

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

static void dahdi_softhangup_all ( void   )  [static]

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

15092 {
15093    struct dahdi_pvt *p;
15094 retry:
15095    ast_mutex_lock(&iflock);
15096    for (p = iflist; p; p = p->next) {
15097       ast_mutex_lock(&p->lock);
15098       if (p->owner && !p->restartpending) {
15099          if (ast_channel_trylock(p->owner)) {
15100             if (option_debug > 2)
15101                ast_verbose("Avoiding deadlock\n");
15102             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15103             ast_mutex_unlock(&p->lock);
15104             ast_mutex_unlock(&iflock);
15105             goto retry;
15106          }
15107          if (option_debug > 2)
15108             ast_verbose("Softhanging up on %s\n", p->owner->name);
15109          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15110          p->restartpending = 1;
15111          num_restart_pending++;
15112          ast_channel_unlock(p->owner);
15113       }
15114       ast_mutex_unlock(&p->lock);
15115    }
15116    ast_mutex_unlock(&iflock);
15117 }

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

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

18461 {
18462    int ctl, res, span;
18463    struct ast_data *data_span, *data_alarms;
18464    struct dahdi_spaninfo s;
18465 
18466    ctl = open("/dev/dahdi/ctl", O_RDWR);
18467    if (ctl < 0) {
18468       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18469       return -1;
18470    }
18471    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18472       s.spanno = span;
18473       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18474       if (res) {
18475          continue;
18476       }
18477 
18478       data_span = ast_data_add_node(data_root, "span");
18479       if (!data_span) {
18480          continue;
18481       }
18482       ast_data_add_str(data_span, "description", s.desc);
18483 
18484       /* insert the alarms status */
18485       data_alarms = ast_data_add_node(data_span, "alarms");
18486       if (!data_alarms) {
18487          continue;
18488       }
18489 
18490       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18491       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18492       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18493       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18494       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18495       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18496 
18497       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18498       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18499       ast_data_add_int(data_span, "crc4", s.crc4count);
18500       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18501                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18502                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18503                      "CAS");
18504       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18505                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18506                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18507                      "Unknown");
18508       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18509                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18510                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18511       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18512 
18513       /* if this span doesn't match remove it. */
18514       if (!ast_data_search_match(search, data_span)) {
18515          ast_data_remove_node(data_root, data_span);
18516       }
18517    }
18518    close(ctl);
18519 
18520    return 0;
18521 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

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

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

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

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

07165 {
07166    /* Unlink a specific slave or all slaves/masters from a given master */
07167    int x;
07168    int hasslaves;
07169    if (!master)
07170       return;
07171    if (needlock) {
07172       ast_mutex_lock(&master->lock);
07173       if (slave) {
07174          while (ast_mutex_trylock(&slave->lock)) {
07175             DEADLOCK_AVOIDANCE(&master->lock);
07176          }
07177       }
07178    }
07179    hasslaves = 0;
07180    for (x = 0; x < MAX_SLAVES; x++) {
07181       if (master->slaves[x]) {
07182          if (!slave || (master->slaves[x] == slave)) {
07183             /* Take slave out of the conference */
07184             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07185             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07186             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07187             master->slaves[x]->master = NULL;
07188             master->slaves[x] = NULL;
07189          } else
07190             hasslaves = 1;
07191       }
07192       if (!hasslaves)
07193          master->inconference = 0;
07194    }
07195    if (!slave) {
07196       if (master->master) {
07197          /* Take master out of the conference */
07198          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07199          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07200          hasslaves = 0;
07201          for (x = 0; x < MAX_SLAVES; x++) {
07202             if (master->master->slaves[x] == master)
07203                master->master->slaves[x] = NULL;
07204             else if (master->master->slaves[x])
07205                hasslaves = 1;
07206          }
07207          if (!hasslaves)
07208             master->master->inconference = 0;
07209       }
07210       master->master = NULL;
07211    }
07212    update_conf(master);
07213    if (needlock) {
07214       if (slave)
07215          ast_mutex_unlock(&slave->lock);
07216       ast_mutex_unlock(&master->lock);
07217    }
07218 }

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

Definition at line 18562 of file chan_dahdi.c.

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

18564 {
18565    int pseudo_fd = -1;
18566    struct dahdi_versioninfo vi = {
18567       .version = "Unknown",
18568       .echo_canceller = "Unknown"
18569    };
18570 
18571    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18572       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18573       return -1;
18574    }
18575 
18576    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18577       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18578    }
18579 
18580    close(pseudo_fd);
18581 
18582    ast_data_add_str(data_root, "value", vi.version);
18583    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18584 
18585    return 0;
18586 }

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

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

Referenced by analog_ss_thread(), and my_wink().

09877 {
09878    int j;
09879    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09880    for (;;)
09881    {
09882       /* set bits of interest */
09883       j = DAHDI_IOMUX_SIGEVENT;
09884       /* wait for some happening */
09885       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09886       /* exit loop if we have it */
09887       if (j & DAHDI_IOMUX_SIGEVENT) break;
09888    }
09889    /* get the event info */
09890    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09891    return 0;
09892 }

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

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

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

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

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

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

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

18125 {
18126    struct ast_cc_config_params *cc_params;
18127 
18128    cc_params = dest->chan.cc_params;
18129    *dest = *src;
18130    dest->chan.cc_params = cc_params;
18131    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18132 }

static void destroy_all_channels ( void   )  [static]

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

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

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

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

05832 {
05833    int i;
05834 
05835    if (!now) {
05836       /* Do not destroy the channel now if it is owned by someone. */
05837       if (cur->owner) {
05838          return;
05839       }
05840       for (i = 0; i < 3; i++) {
05841          if (cur->subs[i].owner) {
05842             return;
05843          }
05844       }
05845    }
05846    destroy_dahdi_pvt(cur);
05847 }

static void destroy_dahdi_pvt ( struct dahdi_pvt pvt  )  [static]

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

05762 {
05763    struct dahdi_pvt *p = pvt;
05764 
05765    if (p->manages_span_alarms) {
05766       struct dahdi_pvt *next = find_next_iface_in_span(p);
05767       if (next) {
05768          next->manages_span_alarms = 1;
05769       }
05770    }
05771 
05772    /* Remove channel from the list */
05773 #if defined(HAVE_PRI)
05774    dahdi_unlink_pri_pvt(p);
05775 #endif   /* defined(HAVE_PRI) */
05776 #if defined(HAVE_SS7)
05777    dahdi_unlink_ss7_pvt(p);
05778 #endif   /* defined(HAVE_SS7) */
05779    switch (pvt->which_iflist) {
05780    case DAHDI_IFLIST_NONE:
05781       break;
05782    case DAHDI_IFLIST_MAIN:
05783       dahdi_iflist_extract(p);
05784       break;
05785 #if defined(HAVE_PRI)
05786    case DAHDI_IFLIST_NO_B_CHAN:
05787       if (p->pri) {
05788          dahdi_nobch_extract(p->pri, p);
05789       }
05790       break;
05791 #endif   /* defined(HAVE_PRI) */
05792    }
05793 
05794    if (p->sig_pvt) {
05795       if (analog_lib_handles(p->sig, 0, 0)) {
05796          analog_delete(p->sig_pvt);
05797       }
05798       switch (p->sig) {
05799 #if defined(HAVE_PRI)
05800       case SIG_PRI_LIB_HANDLE_CASES:
05801          sig_pri_chan_delete(p->sig_pvt);
05802          break;
05803 #endif   /* defined(HAVE_PRI) */
05804 #if defined(HAVE_SS7)
05805       case SIG_SS7:
05806          sig_ss7_chan_delete(p->sig_pvt);
05807          break;
05808 #endif   /* defined(HAVE_SS7) */
05809       default:
05810          break;
05811       }
05812    }
05813    ast_free(p->cidspill);
05814    if (p->use_smdi)
05815       ast_smdi_interface_unref(p->smdi_iface);
05816    if (p->mwi_event_sub)
05817       ast_event_unsubscribe(p->mwi_event_sub);
05818    if (p->vars) {
05819       ast_variables_destroy(p->vars);
05820    }
05821    if (p->cc_params) {
05822       ast_cc_config_params_destroy(p->cc_params);
05823    }
05824    ast_mutex_destroy(&p->lock);
05825    dahdi_close_sub(p, SUB_REAL);
05826    if (p->owner)
05827       p->owner->tech_pvt = NULL;
05828    ast_free(p);
05829 }

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

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

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

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

Definition at line 12299 of file chan_dahdi.c.

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

Referenced by build_channels().

12300 {
12301    struct stat stbuf;
12302    int      num;
12303 
12304    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12305    if (stat(path, &stbuf) < 0) {
12306       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12307       return -errno;
12308    }
12309    if (!S_ISCHR(stbuf.st_mode)) {
12310       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12311       return -EINVAL;
12312    }
12313    num = minor(stbuf.st_rdev);
12314    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12315    return num;
12316 
12317 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 4499 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

04500 {
04501    if (isdigit(digit))
04502       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04503    else if (digit >= 'A' && digit <= 'D')
04504       return DAHDI_TONE_DTMF_A + (digit - 'A');
04505    else if (digit >= 'a' && digit <= 'd')
04506       return DAHDI_TONE_DTMF_A + (digit - 'a');
04507    else if (digit == '*')
04508       return DAHDI_TONE_DTMF_s;
04509    else if (digit == '#')
04510       return DAHDI_TONE_DTMF_p;
04511    else
04512       return -1;
04513 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

06661 {
06662    int val = 0;
06663 
06664    p->ignoredtmf = 1;
06665 
06666    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06667 
06668    if (!p->hardwaredtmf && p->dsp) {
06669       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06670       ast_dsp_set_features(p->dsp, p->dsp_features);
06671    }
06672 }

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

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

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

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

Definition at line 5002 of file chan_dahdi.c.

Referenced by fill_rxgain(), and fill_txgain().

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

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

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

13465 {
13466    struct dahdi_pvt *p;
13467    struct dahdi_bufferinfo bi;
13468    int res;
13469 
13470    p = ast_malloc(sizeof(*p));
13471    if (!p) {
13472       return NULL;
13473    }
13474    *p = *src;
13475 
13476    /* Must deep copy the cc_params. */
13477    p->cc_params = ast_cc_config_params_init();
13478    if (!p->cc_params) {
13479       ast_free(p);
13480       return NULL;
13481    }
13482    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13483 
13484    p->which_iflist = DAHDI_IFLIST_NONE;
13485    p->next = NULL;
13486    p->prev = NULL;
13487    ast_mutex_init(&p->lock);
13488    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13489    if (p->subs[SUB_REAL].dfd < 0) {
13490       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13491       destroy_dahdi_pvt(p);
13492       return NULL;
13493    }
13494    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13495    if (!res) {
13496       bi.txbufpolicy = src->buf_policy;
13497       bi.rxbufpolicy = src->buf_policy;
13498       bi.numbufs = src->buf_no;
13499       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13500       if (res < 0) {
13501          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13502       }
13503    } else
13504       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13505    p->destroy = 1;
13506    dahdi_iflist_insert(p);
13507    return p;
13508 }

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

06675 {
06676    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06677 
06678    if (p->channel == CHAN_PSEUDO)
06679       return;
06680 
06681    p->ignoredtmf = 0;
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 const char * event2str ( int  event  )  [static]

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

04655 {
04656    static char buf[256];
04657    if ((event < (ARRAY_LEN(events))) && (event > -1))
04658       return events[event];
04659    sprintf(buf, "Event %d", event); /* safe */
04660    return buf;
04661 }

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

Definition at line 5066 of file chan_dahdi.c.

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

Referenced by set_actual_rxgain().

05067 {
05068    int j;
05069    int k;
05070    float linear_gain = pow(10.0, gain / 20.0);
05071 
05072    switch (law) {
05073    case DAHDI_LAW_ALAW:
05074       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05075          if (gain || drc) {
05076             k = AST_ALAW(j);
05077             if (drc) {
05078                k = drc_sample(k, drc);
05079             }
05080             k = (float)k*linear_gain;
05081             if (k > 32767) k = 32767;
05082             if (k < -32767) k = -32767;
05083             g->rxgain[j] = AST_LIN2A(k);
05084          } else {
05085             g->rxgain[j] = j;
05086          }
05087       }
05088       break;
05089    case DAHDI_LAW_MULAW:
05090       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05091          if (gain || drc) {
05092             k = AST_MULAW(j);
05093             if (drc) {
05094                k = drc_sample(k, drc);
05095             }
05096             k = (float)k*linear_gain;
05097             if (k > 32767) k = 32767;
05098             if (k < -32767) k = -32767;
05099             g->rxgain[j] = AST_LIN2MU(k);
05100          } else {
05101             g->rxgain[j] = j;
05102          }
05103       }
05104       break;
05105    }
05106 }

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

Definition at line 5022 of file chan_dahdi.c.

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

Referenced by set_actual_txgain().

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

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

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

15938 {
15939    struct dahdi_pvt *p;
15940 
15941    ast_mutex_lock(&iflock);
15942    for (p = iflist; p; p = p->next) {
15943       if (p->channel == channel) {
15944          break;
15945       }
15946    }
15947    ast_mutex_unlock(&iflock);
15948    return p;
15949 }

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

Definition at line 15960 of file chan_dahdi.c.

References find_channel().

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

15961 {
15962    int chan_num;
15963 
15964    if (sscanf(channel, "%30d", &chan_num) != 1) {
15965       /* Not numeric string. */
15966       return NULL;
15967    }
15968 
15969    return find_channel(chan_num);
15970 }

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

Definition at line 5750 of file chan_dahdi.c.

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

Referenced by destroy_dahdi_pvt().

05751 {
05752    if (cur->next && cur->next->span == cur->span) {
05753       return cur->next;
05754    } else if (cur->prev && cur->prev->span == cur->span) {
05755       return cur->prev;
05756    }
05757 
05758    return NULL;
05759 }

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

07747 {
07748    int res;
07749    struct dahdi_spaninfo zi;
07750    struct dahdi_params params;
07751 
07752    memset(&zi, 0, sizeof(zi));
07753    zi.spanno = p->span;
07754 
07755    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07756       if (zi.alarms != DAHDI_ALARM_NONE)
07757          return zi.alarms;
07758    } else {
07759       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07760       return 0;
07761    }
07762 
07763    /* No alarms on the span. Check for channel alarms. */
07764    memset(&params, 0, sizeof(params));
07765    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07766       return params.chan_alarms;
07767 
07768    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07769 
07770    return DAHDI_ALARM_NONE;
07771 }

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

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

07872 {
07873    const char *alarm_str;
07874 
07875 #if defined(HAVE_PRI)
07876    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07877       return;
07878    }
07879 #endif   /* defined(HAVE_PRI) */
07880 
07881    alarm_str = alarm2str(alms);
07882    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07883       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07884       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07885                  "Alarm: %s\r\n"
07886                  "Channel: %d\r\n",
07887                  alarm_str, p->channel);
07888    }
07889 
07890    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07891       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07892       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07893                  "Alarm: %s\r\n"
07894                  "Span: %d\r\n",
07895                  alarm_str, p->span);
07896    }
07897 }

static void handle_clear_alarms ( struct dahdi_pvt p  )  [static]

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

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

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

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

15556 {
15557    int i, j;
15558    switch (cmd) {
15559    case CLI_INIT:
15560       e->command = "dahdi show cadences";
15561       e->usage =
15562          "Usage: dahdi show cadences\n"
15563          "       Shows all cadences currently defined\n";
15564       return NULL;
15565    case CLI_GENERATE:
15566       return NULL;
15567    }
15568    for (i = 0; i < num_cadence; i++) {
15569       char output[1024];
15570       char tmp[16], tmp2[64];
15571       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15572       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15573 
15574       for (j = 0; j < 16; j++) {
15575          if (cadences[i].ringcadence[j] == 0)
15576             break;
15577          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15578          if (cidrings[i] * 2 - 1 == j)
15579             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15580          else
15581             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15582          if (j != 0)
15583             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15584          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15585       }
15586       ast_cli(a->fd,"%s\n",output);
15587    }
15588    return CLI_SUCCESS;
15589 }

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

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

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

static int has_voicemail ( struct dahdi_pvt p  )  [static]

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

05286 {
05287    int new_msgs;
05288    struct ast_event *event;
05289    char *mailbox, *context;
05290 
05291    mailbox = context = ast_strdupa(p->mailbox);
05292    strsep(&context, "@");
05293    if (ast_strlen_zero(context))
05294       context = "default";
05295 
05296    event = ast_event_get_cached(AST_EVENT_MWI,
05297       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05298       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05299       AST_EVENT_IE_END);
05300 
05301    if (event) {
05302       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05303       ast_event_destroy(event);
05304    } else
05305       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05306 
05307    return new_msgs;
05308 }

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

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

Referenced by dahdi_cc_callback(), and dahdi_request().

13224 {
13225 #if defined(HAVE_PRI)
13226    if (0 < span) {
13227       /* The channel must be on the specified PRI span. */
13228       if (!p->pri || p->pri->span != span) {
13229          return 0;
13230       }
13231       if (!groupmatch && channelmatch == -1) {
13232          /* Match any group since it only needs to be on the PRI span. */
13233          *groupmatched = 1;
13234          return 1;
13235       }
13236    }
13237 #endif   /* defined(HAVE_PRI) */
13238    /* check group matching */
13239    if (groupmatch) {
13240       if ((p->group & groupmatch) != groupmatch)
13241          /* Doesn't match the specified group, try the next one */
13242          return 0;
13243       *groupmatched = 1;
13244    }
13245    /* Check to see if we have a channel match */
13246    if (channelmatch != -1) {
13247       if (p->channel != channelmatch)
13248          /* Doesn't match the specified channel, try the next one */
13249          return 0;
13250       *channelmatched = 1;
13251    }
13252 
13253    return 1;
13254 }

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

Definition at line 4767 of file chan_dahdi.c.

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

Referenced by conf_del().

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

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

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

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

static int load_module ( void   )  [static]

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

18610 {
18611    int res;
18612 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18613    int y;
18614 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18615 
18616 #ifdef HAVE_PRI
18617    memset(pris, 0, sizeof(pris));
18618    for (y = 0; y < NUM_SPANS; y++) {
18619       sig_pri_init_pri(&pris[y].pri);
18620    }
18621    pri_set_error(dahdi_pri_error);
18622    pri_set_message(dahdi_pri_message);
18623    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18624 #ifdef HAVE_PRI_PROG_W_CAUSE
18625    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18626 #endif
18627 #if defined(HAVE_PRI_CCSS)
18628    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18629       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18630       __unload_module();
18631       return AST_MODULE_LOAD_FAILURE;
18632    }
18633 #endif   /* defined(HAVE_PRI_CCSS) */
18634    if (sig_pri_load(
18635 #if defined(HAVE_PRI_CCSS)
18636       dahdi_pri_cc_type
18637 #else
18638       NULL
18639 #endif   /* defined(HAVE_PRI_CCSS) */
18640       )) {
18641       __unload_module();
18642       return AST_MODULE_LOAD_FAILURE;
18643    }
18644 #endif
18645 #if defined(HAVE_SS7)
18646    memset(linksets, 0, sizeof(linksets));
18647    for (y = 0; y < NUM_SPANS; y++) {
18648       sig_ss7_init_linkset(&linksets[y].ss7);
18649    }
18650    ss7_set_error(dahdi_ss7_error);
18651    ss7_set_message(dahdi_ss7_message);
18652 #endif   /* defined(HAVE_SS7) */
18653    res = setup_dahdi(0);
18654    /* Make sure we can register our DAHDI channel type */
18655    if (res)
18656       return AST_MODULE_LOAD_DECLINE;
18657    if (ast_channel_register(&dahdi_tech)) {
18658       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18659       __unload_module();
18660       return AST_MODULE_LOAD_FAILURE;
18661    }
18662 #ifdef HAVE_PRI
18663    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18664 #endif
18665 #if defined(HAVE_SS7)
18666    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18667 #endif   /* defined(HAVE_SS7) */
18668 #ifdef HAVE_OPENR2
18669    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18670    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18671 #endif
18672 
18673    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18674    /* register all the data providers */
18675    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18676    memset(round_robin, 0, sizeof(round_robin));
18677    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18678    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18679    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18680    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18681    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18682    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18683    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18684 
18685    ast_cond_init(&ss_thread_complete, NULL);
18686 
18687    return res;
18688 }

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

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

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

11271 {
11272    int x;
11273 
11274 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11275    /* Determine how this spill is to be sent */
11276    if (pvt->mwisend_rpas) {
11277       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11278       pvt->mwisendactive = 1;
11279    } else if (pvt->mwisend_fsk) {
11280       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11281       pvt->mwisendactive = 1;
11282    } else {
11283       pvt->mwisendactive = 0;
11284       return 0;
11285    }
11286 #else
11287    if (mwisend_rpas) {
11288       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11289    } else {
11290       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11291    }
11292    pvt->mwisendactive = 1;
11293 #endif
11294 
11295    if (pvt->cidspill) {
11296       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11297       ast_free(pvt->cidspill);
11298       pvt->cidspill = NULL;
11299       pvt->cidpos = 0;
11300       pvt->cidlen = 0;
11301    }
11302    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11303    if (!pvt->cidspill) {
11304       pvt->mwisendactive = 0;
11305       return -1;
11306    }
11307    x = DAHDI_FLUSH_BOTH;
11308    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11309    x = 3000;
11310    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11311 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11312    if (pvt->mwisend_fsk) {
11313 #endif
11314       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11315                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11316       pvt->cidpos = 0;
11317 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11318    }
11319 #endif
11320    return 0;
11321 }

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

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

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

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

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

11411 {
11412    int handled = 0;
11413 
11414    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11415       switch (event) {
11416       case DAHDI_EVENT_RINGEROFF:
11417          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11418             handled = 1;
11419 
11420             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11421                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11422                ast_free(pvt->cidspill);
11423                pvt->cidspill = NULL;
11424                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11425                pvt->mwisendactive = 0;
11426             } else {
11427                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11428                gettimeofday(&pvt->mwisend_data.pause, NULL);
11429             }
11430          }
11431          break;
11432       /* Going off hook, I need to punt this spill */
11433       case DAHDI_EVENT_RINGOFFHOOK:
11434          if (pvt->cidspill) {
11435             ast_free(pvt->cidspill);
11436             pvt->cidspill = NULL;
11437             pvt->cidpos = 0;
11438             pvt->cidlen = 0;
11439          }
11440          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11441          pvt->mwisendactive = 0;
11442          break;
11443       case DAHDI_EVENT_RINGERON:
11444       case DAHDI_EVENT_HOOKCOMPLETE:
11445          break;
11446       default:
11447          break;
11448       }
11449    }
11450    return handled;
11451 }

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

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

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

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_usec) {
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 9375 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().

09376 {
09377    int sent=0;
09378    int size;
09379    int res;
09380    int fd;
09381    fd = p->subs[idx].dfd;
09382    while (len) {
09383       size = len;
09384       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09385          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09386       res = write(fd, buf, size);
09387       if (res != size) {
09388          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09389          return sent;
09390       }
09391       len -= size;
09392       buf += size;
09393    }
09394    return sent;
09395 }

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 %d\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 1738 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_free(), callerid_get(), CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cs, dahdi_get_event(), dahdievent_to_analogevent(), dahdi_subchannel::dfd, errno, LOG_WARNING, name, analog_pvt::ringt, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.

01739 {
01740    struct dahdi_pvt *p = pvt;
01741    struct analog_pvt *analog_p = p->sig_pvt;
01742    struct pollfd poller;
01743    char *name, *num;
01744    int index = SUB_REAL;
01745    int res;
01746    unsigned char buf[256];
01747    int flags;
01748 
01749    poller.fd = p->subs[SUB_REAL].dfd;
01750    poller.events = POLLPRI | POLLIN;
01751    poller.revents = 0;
01752 
01753    res = poll(&poller, 1, timeout);
01754 
01755    if (poller.revents & POLLPRI) {
01756       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01757       return 1;
01758    }
01759 
01760    if (poller.revents & POLLIN) {
01761       /*** NOTES ***/
01762       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01763        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01764        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01765        * a failure and die, and returning 2 means no event was received. */
01766       res = read(p->subs[index].dfd, buf, sizeof(buf));
01767       if (res < 0) {
01768          if (errno != ELAST) {
01769             ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01770             callerid_free(p->cs);
01771             return -1;
01772          }
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 9857 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by analog_ss_thread().

09858 {
09859    char c;
09860 
09861    *str = 0; /* start with empty output buffer */
09862    for (;;)
09863    {
09864       /* Wait for the first digit (up to specified ms). */
09865       c = ast_waitfordigit(chan, ms);
09866       /* if timeout, hangup or error, return as such */
09867       if (c < 1)
09868          return c;
09869       *str++ = c;
09870       *str = 0;
09871       if (strchr(term, c))
09872          return 1;
09873    }
09874 }

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

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

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

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

03707 {
03708    struct dahdi_pvt *p = pvt;
03709 
03710    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03711       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03712       return 1;
03713    } else {
03714       /* Don't have progress detection. */
03715       return 0;
03716    }
03717 }

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

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

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

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

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

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

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

Definition at line 7061 of file chan_dahdi.c.

References ast_log(), and LOG_WARNING.

Referenced by dahdi_func_write(), and process_dahdi().

07062 {
07063    int res;
07064    char policy_str[21] = "";
07065 
07066    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07067       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07068       return 1;
07069    }
07070    if (*num_buffers < 0) {
07071       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07072       return -1;
07073    }
07074    if (!strcasecmp(policy_str, "full")) {
07075       *policy = DAHDI_POLICY_WHEN_FULL;
07076    } else if (!strcasecmp(policy_str, "immediate")) {
07077       *policy = DAHDI_POLICY_IMMEDIATE;
07078 #if defined(HAVE_DAHDI_HALF_FULL)
07079    } else if (!strcasecmp(policy_str, "half")) {
07080       *policy = DAHDI_POLICY_HALF_FULL;
07081 #endif
07082    } else {
07083       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07084       return -1;
07085    }
07086 
07087    return 0;
07088 }

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

Definition at line 16856 of file chan_dahdi.c.

References string_replace().

Referenced by build_channels().

16857 {
16858    char *p;
16859 
16860    if ((p = strrchr(chanstr, '!')) == NULL) {
16861       *subdir = NULL;
16862       return chanstr;
16863    }
16864    *p++ = '\0';
16865    string_replace(chanstr, '!', '/');
16866    *subdir = chanstr;
16867    return p;
16868 }

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

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

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

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

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

16944 {
16945    char *parse = ast_strdupa(data);
16946    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16947    unsigned int param_count;
16948    unsigned int x;
16949 
16950    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16951       return;
16952 
16953    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16954 
16955    /* first parameter is tap length, process it here */
16956 
16957    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16958 
16959    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16960       confp->chan.echocancel.head.tap_length = x;
16961    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16962       confp->chan.echocancel.head.tap_length = 128;
16963 
16964    /* now process any remaining parameters */
16965 
16966    for (x = 1; x < param_count; x++) {
16967       struct {
16968          char *name;
16969          char *value;
16970       } param;
16971 
16972       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16973          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16974          continue;
16975       }
16976 
16977       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16978          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16979          continue;
16980       }
16981 
16982       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16983 
16984       if (param.value) {
16985          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16986             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16987             continue;
16988          }
16989       }
16990       confp->chan.echocancel.head.param_count++;
16991    }
16992 }

static int reload ( void   )  [static]

Definition at line 18790 of file chan_dahdi.c.

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

18791 {
18792    int res = 0;
18793 
18794    res = setup_dahdi(1);
18795    if (res) {
18796       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18797       return -1;
18798    }
18799    return 0;
18800 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

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

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

static int restart_monitor ( void   )  [static]

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

12007 {
12008    /* If we're supposed to be stopped -- stay stopped */
12009    if (monitor_thread == AST_PTHREADT_STOP)
12010       return 0;
12011    ast_mutex_lock(&monlock);
12012    if (monitor_thread == pthread_self()) {
12013       ast_mutex_unlock(&monlock);
12014       ast_log(LOG_WARNING, "Cannot kill myself\n");
12015       return -1;
12016    }
12017    if (monitor_thread != AST_PTHREADT_NULL) {
12018       /* Wake up the thread */
12019       pthread_kill(monitor_thread, SIGURG);
12020    } else {
12021       /* Start a new monitor */
12022       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12023          ast_mutex_unlock(&monlock);
12024          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12025          return -1;
12026       }
12027    }
12028    ast_mutex_unlock(&monlock);
12029    return 0;
12030 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

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

05255 {
05256    int res;
05257    if (p->saveconf.confmode) {
05258       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05259       p->saveconf.confmode = 0;
05260       if (res) {
05261          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05262          return -1;
05263       }
05264       ast_debug(1, "Restored conferencing\n");
05265    }
05266    return 0;
05267 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

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

05162 {
05163    int res;
05164 
05165    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05166    if (res) {
05167       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05168       return -1;
05169    }
05170 
05171    return 0;
05172 }

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

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

06153 {
06154    if (p->bufferoverrideinuse) {
06155       /* faxbuffers are in use, revert them */
06156       struct dahdi_bufferinfo bi = {
06157          .txbufpolicy = p->buf_policy,
06158          .rxbufpolicy = p->buf_policy,
06159          .bufsize = p->bufsize,
06160          .numbufs = p->buf_no
06161       };
06162       int bpres;
06163 
06164       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06165          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06166       }
06167       p->bufferoverrideinuse = 0;
06168       return bpres;
06169    }
06170 
06171    return -1;
06172 }

static int save_conference ( struct dahdi_pvt p  )  [static]

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

05229 {
05230    struct dahdi_confinfo c;
05231    int res;
05232    if (p->saveconf.confmode) {
05233       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05234       return -1;
05235    }
05236    p->saveconf.chan = 0;
05237    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05238    if (res) {
05239       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05240       p->saveconf.confmode = 0;
05241       return -1;
05242    }
05243    memset(&c, 0, sizeof(c));
05244    c.confmode = DAHDI_CONF_NORMAL;
05245    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05246    if (res) {
05247       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05248       return -1;
05249    }
05250    ast_debug(1, "Disabled conferencing\n");
05251    return 0;
05252 }

static int send_callerid ( struct dahdi_pvt p  )  [static]

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

05313 {
05314    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05315    int res;
05316    /* Take out of linear mode if necessary */
05317    if (p->subs[SUB_REAL].linear) {
05318       p->subs[SUB_REAL].linear = 0;
05319       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05320    }
05321    while (p->cidpos < p->cidlen) {
05322       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05323       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05324       if (res < 0) {
05325          if (errno == EAGAIN)
05326             return 0;
05327          else {
05328             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05329             return -1;
05330          }
05331       }
05332       if (!res)
05333          return 0;
05334       p->cidpos += res;
05335    }
05336    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05337    ast_free(p->cidspill);
05338    p->cidspill = NULL;
05339    if (p->callwaitcas) {
05340       /* Wait for CID/CW to expire */
05341       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05342       p->cid_suppress_expire = p->cidcwexpire;
05343    } else
05344       restore_conference(p);
05345    return 0;
05346 }

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

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

05270 {
05271    p->callwaitcas = 0;
05272    p->cidcwexpire = 0;
05273    p->cid_suppress_expire = 0;
05274    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05275       return -1;
05276    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05277    /* Make sure we account for the end */
05278    p->cidlen += READ_SIZE * 4;
05279    p->cidpos = 0;
05280    send_callerid(p);
05281    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05282    return 0;
05283 }

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

Definition at line 5142 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

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

05143 {
05144    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05145 }

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

Definition at line 5125 of file chan_dahdi.c.

References ast_debug, errno, and fill_rxgain().

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_rxgain(&g, gain, drc, law);
05138 
05139    return ioctl(fd, DAHDI_SETGAINS, &g);
05140 }

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

Definition at line 5108 of file chan_dahdi.c.

References ast_debug, errno, and fill_txgain().

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

05109 {
05110    struct dahdi_gains g;
05111    int res;
05112 
05113    memset(&g, 0, sizeof(g));
05114    res = ioctl(fd, DAHDI_GETGAINS, &g);
05115    if (res) {
05116       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05117       return res;
05118    }
05119 
05120    fill_txgain(&g, gain, drc, law);
05121 
05122    return ioctl(fd, DAHDI_SETGAINS, &g);
05123 }

static int setup_dahdi ( int  reload  )  [static]

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

18434 {
18435    int res;
18436    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18437    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18438    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18439 
18440    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18441       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18442    } else {
18443       res = -1;
18444    }
18445    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18446    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18447    ast_cc_config_params_destroy(conf.chan.cc_params);
18448 
18449    return res;
18450 }

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 18146 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(), restart_monitor(), sig_pri_start_pri(), sig_ss7_linkset::ss7, ss7_linkset(), and ast_variable::value.

Referenced by setup_dahdi().

18147 {
18148    struct ast_config *cfg;
18149    struct ast_config *ucfg;
18150    struct ast_variable *v;
18151    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18152    const char *chans;
18153    const char *cat;
18154    int res;
18155 
18156 #ifdef HAVE_PRI
18157    char *c;
18158    int spanno;
18159    int i;
18160    int logicalspan;
18161    int trunkgroup;
18162    int dchannels[SIG_PRI_NUM_DCHANS];
18163 #endif
18164    int have_cfg_now;
18165    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
18166 
18167    cfg = ast_config_load(config, config_flags);
18168    have_cfg_now = !!cfg;
18169    if (!cfg) {
18170       /* Error if we have no config file */
18171       if (had_cfg_before) {
18172          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18173          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18174       }
18175       cfg = ast_config_new();/* Dummy config */
18176       if (!cfg) {
18177          return 0;
18178       }
18179       ucfg = ast_config_load("users.conf", config_flags);
18180       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18181          ast_config_destroy(cfg);
18182          return 0;
18183       }
18184       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18185          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18186          ast_config_destroy(cfg);
18187          return 0;
18188       }
18189    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18190       ucfg = ast_config_load("users.conf", config_flags);
18191       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18192          return 0;
18193       }
18194       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18195          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18196          return 0;
18197       }
18198       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18199       cfg = ast_config_load(config, config_flags);
18200       have_cfg_now = !!cfg;
18201       if (!cfg) {
18202          if (had_cfg_before) {
18203             /* We should have been able to load the config. */
18204             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18205             ast_config_destroy(ucfg);
18206             return 0;
18207          }
18208          cfg = ast_config_new();/* Dummy config */
18209          if (!cfg) {
18210             ast_config_destroy(ucfg);
18211             return 0;
18212          }
18213       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18214          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18215          ast_config_destroy(ucfg);
18216          return 0;
18217       }
18218    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18219       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18220       return 0;
18221    } else {
18222       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18223       ucfg = ast_config_load("users.conf", config_flags);
18224       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18225          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18226          ast_config_destroy(cfg);
18227          return 0;
18228       }
18229    }
18230    had_cfg_before = have_cfg_now;
18231 
18232    /* It's a little silly to lock it, but we might as well just to be sure */
18233    ast_mutex_lock(&iflock);
18234 #ifdef HAVE_PRI
18235    if (reload != 1) {
18236       /* Process trunkgroups first */
18237       v = ast_variable_browse(cfg, "trunkgroups");
18238       while (v) {
18239          if (!strcasecmp(v->name, "trunkgroup")) {
18240             trunkgroup = atoi(v->value);
18241             if (trunkgroup > 0) {
18242                if ((c = strchr(v->value, ','))) {
18243                   i = 0;
18244                   memset(dchannels, 0, sizeof(dchannels));
18245                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18246                      dchannels[i] = atoi(c + 1);
18247                      if (dchannels[i] < 0) {
18248                         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);
18249                      } else
18250                         i++;
18251                      c = strchr(c + 1, ',');
18252                   }
18253                   if (i) {
18254                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18255                         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);
18256                   } else
18257                         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");
18258                   } else
18259                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18260                } else
18261                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18262             } else
18263                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18264          } else if (!strcasecmp(v->name, "spanmap")) {
18265             spanno = atoi(v->value);
18266             if (spanno > 0) {
18267                if ((c = strchr(v->value, ','))) {
18268                   trunkgroup = atoi(c + 1);
18269                   if (trunkgroup > 0) {
18270                      if ((c = strchr(c + 1, ',')))
18271                         logicalspan = atoi(c + 1);
18272                      else
18273                         logicalspan = 0;
18274                      if (logicalspan >= 0) {
18275                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18276                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18277                      } else
18278                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18279                      } else
18280                         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);
18281                   } else
18282                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18283                } else
18284                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18285             } else
18286                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18287          } else {
18288             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18289          }
18290          v = v->next;
18291       }
18292    }
18293 #endif
18294 
18295    /* Copy the default jb config over global_jbconf */
18296    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18297 
18298    mwimonitornotify[0] = '\0';
18299 
18300    v = ast_variable_browse(cfg, "channels");
18301    if ((res = process_dahdi(base_conf,
18302       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18303       v, reload, 0))) {
18304       ast_mutex_unlock(&iflock);
18305       ast_config_destroy(cfg);
18306       if (ucfg) {
18307          ast_config_destroy(ucfg);
18308       }
18309       return res;
18310    }
18311 
18312    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18313    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18314       /* [channels] and [trunkgroups] are used. Let's also reserve
18315        * [globals] and [general] for future use
18316        */
18317       if (!strcasecmp(cat, "general") ||
18318          !strcasecmp(cat, "trunkgroups") ||
18319          !strcasecmp(cat, "globals") ||
18320          !strcasecmp(cat, "channels")) {
18321          continue;
18322       }
18323 
18324       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18325       if (ast_strlen_zero(chans)) {
18326          /* Section is useless without a dahdichan value present. */
18327          continue;
18328       }
18329 
18330       /* Copy base_conf to conf. */
18331       deep_copy_dahdi_chan_conf(conf, base_conf);
18332 
18333       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18334          ast_mutex_unlock(&iflock);
18335          ast_config_destroy(cfg);
18336          if (ucfg) {
18337             ast_config_destroy(ucfg);
18338          }
18339          return res;
18340       }
18341    }
18342 
18343    ast_config_destroy(cfg);
18344 
18345    if (ucfg) {
18346       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18347       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18348       process_dahdi(base_conf,
18349          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18350          ast_variable_browse(ucfg, "general"), 1, 0);
18351 
18352       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18353          if (!strcasecmp(cat, "general")) {
18354             continue;
18355          }
18356 
18357          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18358          if (ast_strlen_zero(chans)) {
18359             /* Section is useless without a dahdichan value present. */
18360             continue;
18361          }
18362 
18363          /* Copy base_conf to conf. */
18364          deep_copy_dahdi_chan_conf(conf, base_conf);
18365 
18366          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18367             ast_config_destroy(ucfg);
18368             ast_mutex_unlock(&iflock);
18369             return res;
18370          }
18371       }
18372       ast_config_destroy(ucfg);
18373    }
18374    ast_mutex_unlock(&iflock);
18375 
18376 #ifdef HAVE_PRI
18377    if (reload != 1) {
18378       int x;
18379       for (x = 0; x < NUM_SPANS; x++) {
18380          if (pris[x].pri.pvts[0]) {
18381             prepare_pri(pris + x);
18382             if (sig_pri_start_pri(&pris[x].pri)) {
18383                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18384                return -1;
18385             } else
18386                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18387          }
18388       }
18389    }
18390 #endif
18391 #if defined(HAVE_SS7)
18392    if (reload != 1) {
18393       int x;
18394       for (x = 0; x < NUM_SPANS; x++) {
18395          if (linksets[x].ss7.ss7) {
18396             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18397             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18398                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18399                return -1;
18400             } else
18401                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18402          }
18403       }
18404    }
18405 #endif   /* defined(HAVE_SS7) */
18406 #ifdef HAVE_OPENR2
18407    if (reload != 1) {
18408       int x;
18409       for (x = 0; x < r2links_count; x++) {
18410          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18411             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18412             return -1;
18413          } else {
18414             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18415          }
18416       }
18417    }
18418 #endif
18419    /* And start the monitor for the first time */
18420    restart_monitor();
18421    return 0;
18422 }

static int sigtype_to_signalling ( int  sigtype  )  [static]

Definition at line 12282 of file chan_dahdi.c.

Referenced by mkintf().

12283 {
12284    return sigtype;
12285 }

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

Definition at line 16847 of file chan_dahdi.c.

Referenced by parse_spanchan().

16848 {
16849    for (; *str; str++) {
16850       if (*str == char1) {
16851          *str = char2;
16852       }
16853    }
16854 }

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

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

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

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

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

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

static int unload_module ( void   )  [static]

Definition at line 16831 of file chan_dahdi.c.

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

16832 {
16833 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16834    int y;
16835 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16836 #ifdef HAVE_PRI
16837    for (y = 0; y < NUM_SPANS; y++)
16838       ast_mutex_destroy(&pris[y].pri.lock);
16839 #endif
16840 #if defined(HAVE_SS7)
16841    for (y = 0; y < NUM_SPANS; y++)
16842       ast_mutex_destroy(&linksets[y].ss7.lock);
16843 #endif   /* defined(HAVE_SS7) */
16844    return __unload_module();
16845 }

static int update_conf ( struct dahdi_pvt p  )  [static]

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

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

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

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

03844 {
03845    dahdi_lock_sub_owner(p, a);
03846    if (p->subs[a].owner) {
03847       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03848       ast_channel_unlock(p->subs[a].owner);
03849    }
03850 }


Variable Documentation

int alarm

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

Initial value:

Definition at line 18593 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

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

Initial value:

Definition at line 18588 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 1518 of file chan_dahdi.c.

Initial value:

Definition at line 18598 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 4609 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 1322 of file chan_dahdi.c.

struct dahdi_pvt* iflist = NULL [static]

Main interface list start

Definition at line 1321 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 4633 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 3790 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 634 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 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1