Thu Apr 3 08:21:11 2014

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"
Include dependency graph for chan_dahdi.c:

Go to the source code of this file.

Data Structures

struct  dahdi_chan_conf
 Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section of chan_dahdi.conf. Generally there is a field here for every possible configuration item. More...
struct  dahdi_distRings
struct  dahdi_pvt
struct  dahdi_starting_point
struct  dahdi_subchannel
struct  distRingData
struct  mwi_thread_data
struct  mwisend_info
struct  ringContextData

Defines

#define ASCII_BYTES_PER_CHAR   80
#define AST_LAW(p)   (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
#define CALLPROGRESS_FAX_INCOMING   4
#define CALLPROGRESS_FAX_OUTGOING   2
#define CALLPROGRESS_PROGRESS   1
#define CALLWAITING_REPEAT_SAMPLES   ((10000 * 8) / READ_SIZE)
#define CALLWAITING_SILENT_SAMPLES   ((300 * 8) / READ_SIZE)
#define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE)
#define CANBUSYDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
#define CANPROGRESSDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
#define CHAN_PSEUDO   -2
#define CIDCW_EXPIRE_SAMPLES   ((500 * 8) / READ_SIZE)
#define CONF_USER_REAL   (1 << 0)
#define CONF_USER_THIRDCALL   (1 << 1)
#define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
#define DATA_EXPORT_DAHDI_PVT(MEMBER)
#define DEFAULT_CIDRINGS   1
 Typically, how many rings before we should send Caller*ID.
#define DEFAULT_RINGT   ((8000 * 8) / READ_SIZE)
#define END_SILENCE_LEN   400
#define FORMAT   "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT   "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define FORMAT2   "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT2   "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define GET_CHANNEL(p)   ((p)->channel)
#define HANGUP   1
#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)
#define HEADER_MS   50
#define ISTRUNK(p)
#define MASK_AVAIL   (1 << 0)
#define MASK_INUSE   (1 << 1)
#define MAX_CHANLIST_LEN   80
#define MAX_SLAVES   4
#define MIN_MS_SINCE_FLASH   ((2000) )
#define NEED_MFDETECT(p)   (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
 Signaling types that need to use MF detection should be placed in this macro.
#define NUM_CADENCE_MAX   25
#define NUM_SPANS   32
#define POLARITY_IDLE   0
#define POLARITY_REV   1
#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)
#define PROC_DAHDI_OPT_NOWARN   (1 << 1)
#define READ_SIZE   160
#define REPORT_CHANNEL_ALARMS   1
#define REPORT_SPAN_ALARMS   2
#define sig2str   dahdi_sig2str
#define SIG_BRI   (0x2000000 | DAHDI_SIG_CLEAR)
#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)
#define SIG_E911   (0x1000000 | DAHDI_SIG_EM)
#define SIG_EM   DAHDI_SIG_EM
#define SIG_EM_E1   DAHDI_SIG_EM_E1
#define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)
#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)
#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)
#define SIG_FXOGS   DAHDI_SIG_FXOGS
#define SIG_FXOKS   DAHDI_SIG_FXOKS
#define SIG_FXOLS   DAHDI_SIG_FXOLS
#define SIG_FXSGS   DAHDI_SIG_FXSGS
#define SIG_FXSKS   DAHDI_SIG_FXSKS
#define SIG_FXSLS   DAHDI_SIG_FXSLS
#define SIG_MFCR2   DAHDI_SIG_CAS
#define SIG_PRI   DAHDI_SIG_CLEAR
#define SIG_PRI_LIB_HANDLE_CASES
#define SIG_SF   DAHDI_SIG_SF
#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)
#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)
#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
#define SIG_SS7   (0x1000000 | DAHDI_SIG_CLEAR)
#define SMDI_MD_WAIT_TIMEOUT   1500
#define SUB_CALLWAIT   1
#define SUB_REAL   0
#define SUB_THREEWAY   2
#define TRAILER_MS   5
#define TRANSFER   0

Enumerations

enum  DAHDI_IFLIST { DAHDI_IFLIST_NONE, DAHDI_IFLIST_MAIN }
enum  mwisend_states {
  MWI_SEND_NULL = 0, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_PAUSE,
  MWI_SEND_SPILL, MWI_SEND_CLEANUP, MWI_SEND_DONE
}

Functions

static struct ast_frame__dahdi_exception (struct ast_channel *ast)
static int __unload_module (void)
static int _dahdi_get_index (struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
static int action_dahdidialoffhook (struct mansession *s, const struct message *m)
static int action_dahdidndoff (struct mansession *s, const struct message *m)
static int action_dahdidndon (struct mansession *s, const struct message *m)
static int action_dahdirestart (struct mansession *s, const struct message *m)
static int action_dahdishowchannels (struct mansession *s, const struct message *m)
static int action_transfer (struct mansession *s, const struct message *m)
static int action_transferhangup (struct mansession *s, const struct message *m)
static char * alarm2str (int alm)
static int alloc_sub (struct dahdi_pvt *p, int x)
static int analog_lib_handles (int signalling, int radio, int oprmode)
static void * analog_ss_thread (void *data)
static int analog_tone_to_dahditone (enum analog_tone tone)
static int analogsub_to_dahdisub (enum analog_sub analogsub)
 AST_DATA_STRUCTURE (dahdi_pvt, DATA_EXPORT_DAHDI_PVT)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DRIVER,.nonoptreq="res_smdi",)
 AST_MUTEX_DEFINE_STATIC (restart_lock)
 AST_MUTEX_DEFINE_STATIC (ss_thread_lock)
 AST_MUTEX_DEFINE_STATIC (monlock)
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
 AST_MUTEX_DEFINE_STATIC (iflock)
 Protect the interface list (of dahdi_pvt's).
static int attempt_transfer (struct dahdi_pvt *p)
static int available (struct dahdi_pvt **pvt, int is_specific_channel)
static int build_channels (struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
static int bump_gains (struct dahdi_pvt *p)
static int calc_energy (const unsigned char *buf, int len, format_t law)
static int canmatch_featurecode (const char *exten)
static int check_for_conference (struct dahdi_pvt *p)
static int conf_add (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
static int conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
static struct ast_strcreate_channel_name (struct dahdi_pvt *i)
static void dahdi_ami_channel_event (struct dahdi_pvt *p, struct ast_channel *chan)
static int dahdi_answer (struct ast_channel *ast)
static enum ast_bridge_result dahdi_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int dahdi_call (struct ast_channel *ast, char *rdest, int timeout)
static int dahdi_callwait (struct ast_channel *ast)
static int dahdi_cc_callback (struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
 Callback made when dial failed to get a channel out of dahdi_request().
static struct dahdi_chan_conf dahdi_chan_conf_default (void)
static int dahdi_channels_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static void dahdi_close (int fd)
static void dahdi_close_sub (struct dahdi_pvt *chan_pvt, int sub_num)
static int dahdi_confmute (struct dahdi_pvt *p, int muted)
static char * dahdi_destroy_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_destroy_channel_bynum (int channel)
static int dahdi_devicestate (void *data)
static int dahdi_digit_begin (struct ast_channel *ast, char digit)
static int dahdi_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static void dahdi_disable_ec (struct dahdi_pvt *p)
static int dahdi_dnd (struct dahdi_pvt *dahdichan, int flag)
 enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
static void dahdi_enable_ec (struct dahdi_pvt *p)
static struct ast_framedahdi_exception (struct ast_channel *ast)
static int dahdi_fake_event (struct dahdi_pvt *p, int mode)
static int dahdi_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int dahdi_func_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
static int dahdi_func_write (struct ast_channel *chan, const char *function, char *data, const char *value)
static int dahdi_get_event (int fd)
 Avoid the silly dahdi_getevent which ignores a bunch of events.
static void dahdi_handle_dtmf (struct ast_channel *ast, int idx, struct ast_frame **dest)
static struct ast_framedahdi_handle_event (struct ast_channel *ast)
static int dahdi_hangup (struct ast_channel *ast)
static void dahdi_iflist_extract (struct dahdi_pvt *pvt)
static void dahdi_iflist_insert (struct dahdi_pvt *pvt)
static int dahdi_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen)
static void dahdi_link (struct dahdi_pvt *slave, struct dahdi_pvt *master)
static void dahdi_lock_sub_owner (struct dahdi_pvt *pvt, int sub_idx)
static struct ast_channeldahdi_new (struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
static int dahdi_open (char *fn)
static int dahdi_queryoption (struct ast_channel *chan, int option, void *data, int *datalen)
static void dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f)
static struct ast_framedahdi_read (struct ast_channel *ast)
static struct ast_channeldahdi_request (const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
static int dahdi_restart (void)
static char * dahdi_restart_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_ring_phone (struct dahdi_pvt *p)
static int dahdi_sendtext (struct ast_channel *c, const char *text)
static char * dahdi_set_dnd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_set_hook (int fd, int hs)
static char * dahdi_set_hwgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_set_swgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_setlinear (int dfd, int linear)
static int dahdi_setoption (struct ast_channel *chan, int option, void *data, int datalen)
static char * dahdi_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_sig2str (int sig)
static int dahdi_sig_pri_lib_handles (int signaling)
static void dahdi_softhangup_all (void)
static int dahdi_status_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static void dahdi_train_ec (struct dahdi_pvt *p)
static void dahdi_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
static int dahdi_version_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static int dahdi_wait_event (int fd)
 Avoid the silly dahdi_waitevent which ignores a bunch of events.
static int dahdi_wink (struct dahdi_pvt *p, int index)
static int dahdi_write (struct ast_channel *ast, struct ast_frame *frame)
static enum analog_event dahdievent_to_analogevent (int event)
static enum analog_sigtype dahdisig_to_analogsig (int sig)
static void deep_copy_dahdi_chan_conf (struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
static void destroy_all_channels (void)
static void destroy_channel (struct dahdi_pvt *cur, int now)
static void destroy_dahdi_pvt (struct dahdi_pvt *pvt)
static struct dahdi_pvtdetermine_starting_point (const char *data, struct dahdi_starting_point *param)
static int device2chan (const char *subdir, int channel, char *path, int pathlen)
static int digit_to_dtmfindex (char digit)
static void disable_dtmf_detect (struct dahdi_pvt *p)
static void * do_monitor (void *data)
static int drc_sample (int sample, float drc)
static struct dahdi_pvtduplicate_pseudo (struct dahdi_pvt *src)
static void enable_dtmf_detect (struct dahdi_pvt *p)
static const char * event2str (int event)
static void fill_rxgain (struct dahdi_gains *g, float gain, float drc, int law)
static void fill_txgain (struct dahdi_gains *g, float gain, float drc, int law)
static struct dahdi_pvtfind_channel (int channel)
static struct dahdi_pvtfind_channel_from_str (const char *channel)
static struct dahdi_pvtfind_next_iface_in_span (struct dahdi_pvt *cur)
static int get_alarms (struct dahdi_pvt *p)
static void handle_alarms (struct dahdi_pvt *p, int alms)
static void handle_clear_alarms (struct dahdi_pvt *p)
static char * handle_dahdi_show_cadences (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct dahdi_pvthandle_init_event (struct dahdi_pvt *i, int event)
static int has_voicemail (struct dahdi_pvt *p)
static int is_group_or_channel_match (struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
static int isourconf (struct dahdi_pvt *p, struct dahdi_subchannel *c)
static int isslavenative (struct dahdi_pvt *p, struct dahdi_pvt **out)
static int load_module (void)
static struct dahdi_pvtmkintf (int channel, const struct dahdi_chan_conf *conf, int reloading)
static void monitor_pfds_clean (void *arg)
static void mwi_event_cb (const struct ast_event *event, void *userdata)
static int mwi_send_init (struct dahdi_pvt *pvt)
static int mwi_send_process_buffer (struct dahdi_pvt *pvt, int num_read)
static int mwi_send_process_event (struct dahdi_pvt *pvt, int event)
static void * mwi_thread (void *data)
static void my_all_subchannels_hungup (void *pvt)
static int my_allocate_sub (void *pvt, enum analog_sub analogsub)
static void my_answer_polarityswitch (void *pvt)
static int my_callwait (void *pvt)
static void my_cancel_cidspill (void *pvt)
static int my_check_confirmanswer (void *pvt)
static int my_check_for_conference (void *pvt)
static int my_check_waitingfordt (void *pvt)
static int my_complete_conference_update (void *pvt, int needconference)
static int my_conf_add (void *pvt, enum analog_sub sub)
static int my_conf_del (void *pvt, enum analog_sub sub)
static int my_confmute (void *pvt, int mute)
static int my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
static void my_deadlock_avoidance_private (void *pvt)
static void my_decrease_ss_count (void)
static int my_dial_digits (void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
static int my_distinctive_ring (struct ast_channel *chan, void *pvt, int idx, int *ringdata)
static int my_dsp_reset_and_flush_digits (void *pvt)
static int my_dsp_set_digitmode (void *pvt, enum analog_dsp_digitmode mode)
static int my_flash (void *pvt)
static void my_get_and_handle_alarms (void *pvt)
static int my_get_callerid (void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
static int my_get_event (void *pvt)
static const char * my_get_orig_dialstring (void *pvt)
static void * my_get_sigpvt_bridged_channel (struct ast_channel *chan)
static int my_get_sub_fd (void *pvt, enum analog_sub sub)
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
static void my_handle_dtmf (void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
static void my_handle_notify_message (struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
static void my_hangup_polarityswitch (void *pvt)
static int my_has_voicemail (void *pvt)
static int my_have_progressdetect (void *pvt)
static void my_increase_ss_count (void)
static int my_is_dialing (void *pvt, enum analog_sub sub)
static int my_is_off_hook (void *pvt)
static void my_lock_private (void *pvt)
static struct ast_channelmy_new_analog_ast_channel (void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
static int my_off_hook (void *pvt)
static int my_on_hook (void *pvt)
static int my_play_tone (void *pvt, enum analog_sub sub, enum analog_tone tone)
static int my_ring (void *pvt)
static int my_send_callerid (void *pvt, int cwcid, struct ast_party_caller *caller)
static void my_set_alarm (void *pvt, int in_alarm)
static void my_set_cadence (void *pvt, int *cid_rings, struct ast_channel *ast)
static void my_set_callwaiting (void *pvt, int callwaiting_enable)
static void my_set_confirmanswer (void *pvt, int flag)
static void my_set_dialing (void *pvt, int is_dialing)
static int my_set_echocanceller (void *pvt, int enable)
static void my_set_inthreeway (void *pvt, enum analog_sub sub, int inthreeway)
static int my_set_linear_mode (void *pvt, enum analog_sub sub, int linear_mode)
static void my_set_needringing (void *pvt, int value)
static void my_set_new_owner (void *pvt, struct ast_channel *new_owner)
static void my_set_outgoing (void *pvt, int is_outgoing)
static void my_set_polarity (void *pvt, int value)
static void my_set_pulsedial (void *pvt, int flag)
static void my_set_ringtimeout (void *pvt, int ringt)
static void my_set_waitingfordt (void *pvt, struct ast_channel *ast)
static int my_start (void *pvt)
static int my_start_cid_detect (void *pvt, int cid_signalling)
static void my_start_polarityswitch (void *pvt)
static int my_stop_callwait (void *pvt)
static int my_stop_cid_detect (void *pvt)
static void my_swap_subchannels (void *pvt, enum analog_sub a, struct ast_channel *ast_a, enum analog_sub b, struct ast_channel *ast_b)
static int my_train_echocanceller (void *pvt)
static int my_unallocate_sub (void *pvt, enum analog_sub analogsub)
static void my_unlock_private (void *pvt)
static int my_wait_event (void *pvt)
static int my_wink (void *pvt, enum analog_sub sub)
static void notify_message (char *mailbox_full, int thereornot)
 Send MWI state change.
static int parse_buffers_policy (const char *parse, int *num_buffers, int *policy)
static char * parse_spanchan (char *chanstr, char **subdir)
static int process_dahdi (struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
static void process_echocancel (struct dahdi_chan_conf *confp, const char *data, unsigned int line)
static int reload (void)
static int reset_conf (struct dahdi_pvt *p)
static int restart_monitor (void)
static int restore_conference (struct dahdi_pvt *p)
static int restore_gains (struct dahdi_pvt *p)
static int revert_fax_buffers (struct dahdi_pvt *p, struct ast_channel *ast)
static int save_conference (struct dahdi_pvt *p)
static int send_callerid (struct dahdi_pvt *p)
static int send_cwcidspill (struct dahdi_pvt *p)
static int set_actual_gain (int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
static int set_actual_rxgain (int fd, float gain, float drc, int law)
static int set_actual_txgain (int fd, float gain, float drc, int law)
static int setup_dahdi (int reload)
static int setup_dahdi_int (int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
static int sigtype_to_signalling (int sigtype)
static void string_replace (char *str, int char1, int char2)
static void swap_subs (struct dahdi_pvt *p, int a, int b)
static int unalloc_sub (struct dahdi_pvt *p, int x)
static int unload_module (void)
static int update_conf (struct dahdi_pvt *p)
static void wakeup_sub (struct dahdi_pvt *p, int a)

Variables

struct {
   int   alarm
   char *   name
alarms []
static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
static int cidrings [NUM_CADENCE_MAX]
 cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.
static const char config [] = "chan_dahdi.conf"
static struct analog_callback dahdi_analog_callbacks
static struct ast_data_handler dahdi_channels_data_provider
static struct ast_cli_entry dahdi_cli []
static struct ast_data_entry dahdi_data_providers []
static struct ast_data_handler dahdi_status_data_provider
static struct ast_channel_tech dahdi_tech
static struct ast_data_handler dahdi_version_data_provider
static struct ast_jb_conf default_jbconf
static char defaultcic [64] = ""
static char defaultozz [64] = ""
static int distinctiveringaftercid = 0
static int dtmfcid_level = 256
static const char *const events []
static int firstdigittimeout = 16000
 Wait up to 16 seconds for first digit (FXO logic).
static int gendigittimeout = 8000
 How long to wait for following digits (FXO logic).
static struct ast_jb_conf global_jbconf
static int ifcount = 0
static struct dahdi_pvtifend = NULL
static struct dahdi_pvtiflist = NULL
static const char *const lbostr []
static int matchdigittimeout = 3000
 How long to wait for an extra digit, if there is an ambiguous match.
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use.
static int mwilevel = 512
static char mwimonitornotify [PATH_MAX] = ""
static int mwisend_rpas = 0
static int num_cadence = 4
static int num_restart_pending = 0
static int numbufs = 4
static char progzone [10] = ""
static int report_alarms = REPORT_CHANNEL_ALARMS
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base.
static struct dahdi_pvtround_robin [32]
static ast_cond_t ss_thread_complete
static int ss_thread_count = 0
static const char *const subnames []
static const char tdesc [] = "DAHDI Telephony Driver"
static int usedistinctiveringdetection = 0
static int user_has_defined_cadences = 0

Detailed Description

DAHDI for Pseudo TDM.

Author:
Mark Spencer <markster@digium.com>

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

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

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

Definition in file chan_dahdi.c.


Define Documentation

#define ASCII_BYTES_PER_CHAR   80

Referenced by dahdi_sendtext().

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

Definition at line 387 of file chan_dahdi.c.

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

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 386 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 385 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_PROGRESS   1

Definition at line 384 of file chan_dahdi.c.

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

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

10,000 ms

Definition at line 522 of file chan_dahdi.c.

Referenced by dahdi_callwait(), and my_callwait().

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

300 ms

Definition at line 521 of file chan_dahdi.c.

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

100 ms

Definition at line 523 of file chan_dahdi.c.

Referenced by send_callerid().

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

Definition at line 417 of file chan_dahdi.c.

Referenced by dahdi_new().

#define CANPROGRESSDETECT (  )     (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
#define CHAN_PSEUDO   -2
#define CIDCW_EXPIRE_SAMPLES   ((500 * 8) / READ_SIZE)

500 ms

Definition at line 524 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 659 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 660 of file chan_dahdi.c.

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

Definition at line 1236 of file chan_dahdi.c.

#define DEFAULT_CIDRINGS   1

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

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

Definition at line 318 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

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

8,000 ms

Definition at line 526 of file chan_dahdi.c.

#define END_SILENCE_LEN   400

Referenced by dahdi_sendtext().

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

Definition at line 1525 of file chan_dahdi.c.

Referenced by my_complete_conference_update(), and update_conf().

#define HANGUP   1

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

#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 16938 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 16992 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 16994 of file chan_dahdi.c.

Referenced by process_dahdi(), and setup_dahdi_int().

#define READ_SIZE   160

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

Definition at line 516 of file chan_dahdi.c.

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

#define REPORT_CHANNEL_ALARMS   1

Definition at line 439 of file chan_dahdi.c.

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

#define REPORT_SPAN_ALARMS   2

Definition at line 440 of file chan_dahdi.c.

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

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

Definition at line 365 of file chan_dahdi.c.

Referenced by dahdi_sig2str(), and process_dahdi().

#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)

Definition at line 366 of file chan_dahdi.c.

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

#define SIG_E911   (0x1000000 | DAHDI_SIG_EM)
#define SIG_EM   DAHDI_SIG_EM
#define SIG_EM_E1   DAHDI_SIG_EM_E1
#define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)
#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)
#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)
#define SIG_FXOGS   DAHDI_SIG_FXOGS
#define SIG_FXOKS   DAHDI_SIG_FXOKS
#define SIG_FXOLS   DAHDI_SIG_FXOLS
#define SIG_FXSGS   DAHDI_SIG_FXSGS
#define SIG_FXSKS   DAHDI_SIG_FXSKS
#define SIG_FXSLS   DAHDI_SIG_FXSLS
#define SIG_MFCR2   DAHDI_SIG_CAS
#define SIG_PRI   DAHDI_SIG_CLEAR

Definition at line 364 of file chan_dahdi.c.

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

#define SIG_PRI_LIB_HANDLE_CASES
#define SIG_SF   DAHDI_SIG_SF
#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)
#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)
#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
#define SIG_SS7   (0x1000000 | DAHDI_SIG_CLEAR)
#define SMDI_MD_WAIT_TIMEOUT   1500

Definition at line 281 of file chan_dahdi.c.

Referenced by analog_ss_thread().

#define SUB_CALLWAIT   1
#define SUB_REAL   0

Active call

Definition at line 614 of file chan_dahdi.c.

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

#define SUB_THREEWAY   2
#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

Enumeration Type Documentation

Specify the lists dahdi_pvt can be put in.

Enumerator:
DAHDI_IFLIST_NONE 

The dahdi_pvt is not in any list.

DAHDI_IFLIST_MAIN 

The dahdi_pvt is in the main interface list

Definition at line 683 of file chan_dahdi.c.

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

Enumerator:
MWI_SEND_NULL 
MWI_SEND_SA 
MWI_SEND_SA_WAIT 
MWI_SEND_PAUSE 
MWI_SEND_SPILL 
MWI_SEND_CLEANUP 
MWI_SEND_DONE 

Definition at line 667 of file chan_dahdi.c.

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


Function Documentation

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

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

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

static int __unload_module ( void   )  [static]

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

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

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

03773 {
03774    int res;
03775    if (p->subs[SUB_REAL].owner == ast)
03776       res = 0;
03777    else if (p->subs[SUB_CALLWAIT].owner == ast)
03778       res = 1;
03779    else if (p->subs[SUB_THREEWAY].owner == ast)
03780       res = 2;
03781    else {
03782       res = -1;
03783       if (!nullok)
03784          ast_log(LOG_WARNING,
03785             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03786             ast ? ast->name : "", p->channel, fname, line);
03787    }
03788    return res;
03789 }

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

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

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

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

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

15983 {
15984    struct dahdi_pvt *p;
15985    const char *channel = astman_get_header(m, "DAHDIChannel");
15986 
15987    if (ast_strlen_zero(channel)) {
15988       astman_send_error(s, m, "No channel specified");
15989       return 0;
15990    }
15991    p = find_channel_from_str(channel);
15992    if (!p) {
15993       astman_send_error(s, m, "No such channel");
15994       return 0;
15995    }
15996    dahdi_dnd(p, 0);
15997    astman_send_ack(s, m, "DND Disabled");
15998    return 0;
15999 }

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

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

15964 {
15965    struct dahdi_pvt *p;
15966    const char *channel = astman_get_header(m, "DAHDIChannel");
15967 
15968    if (ast_strlen_zero(channel)) {
15969       astman_send_error(s, m, "No channel specified");
15970       return 0;
15971    }
15972    p = find_channel_from_str(channel);
15973    if (!p) {
15974       astman_send_error(s, m, "No such channel");
15975       return 0;
15976    }
15977    dahdi_dnd(p, 1);
15978    astman_send_ack(s, m, "DND Enabled");
15979    return 0;
15980 }

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

Definition at line 15252 of file chan_dahdi.c.

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

Referenced by load_module().

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

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

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

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

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

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

16002 {
16003    struct dahdi_pvt *p;
16004    const char *channel = astman_get_header(m, "DAHDIChannel");
16005 
16006    if (ast_strlen_zero(channel)) {
16007       astman_send_error(s, m, "No channel specified");
16008       return 0;
16009    }
16010    p = find_channel_from_str(channel);
16011    if (!p) {
16012       astman_send_error(s, m, "No such channel");
16013       return 0;
16014    }
16015    if (!analog_lib_handles(p->sig, 0, 0)) {
16016       astman_send_error(s, m, "Channel signaling is not analog");
16017       return 0;
16018    }
16019    dahdi_fake_event(p,TRANSFER);
16020    astman_send_ack(s, m, "DAHDITransfer");
16021    return 0;
16022 }

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

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

16025 {
16026    struct dahdi_pvt *p;
16027    const char *channel = astman_get_header(m, "DAHDIChannel");
16028 
16029    if (ast_strlen_zero(channel)) {
16030       astman_send_error(s, m, "No channel specified");
16031       return 0;
16032    }
16033    p = find_channel_from_str(channel);
16034    if (!p) {
16035       astman_send_error(s, m, "No such channel");
16036       return 0;
16037    }
16038    if (!analog_lib_handles(p->sig, 0, 0)) {
16039       astman_send_error(s, m, "Channel signaling is not analog");
16040       return 0;
16041    }
16042    dahdi_fake_event(p,HANGUP);
16043    astman_send_ack(s, m, "DAHDIHangup");
16044    return 0;
16045 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 4623 of file chan_dahdi.c.

References alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

04624 {
04625    int x;
04626    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04627       if (alarms[x].alarm & alm)
04628          return alarms[x].name;
04629    }
04630    return alm ? "Unknown Alarm" : "No Alarm";
04631 }

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

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

04425 {
04426    struct dahdi_bufferinfo bi;
04427    int res;
04428    if (p->subs[x].dfd >= 0) {
04429       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04430       return -1;
04431    }
04432 
04433    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04434    if (p->subs[x].dfd <= -1) {
04435       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04436       return -1;
04437    }
04438 
04439    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04440    if (!res) {
04441       bi.txbufpolicy = p->buf_policy;
04442       bi.rxbufpolicy = p->buf_policy;
04443       bi.numbufs = p->buf_no;
04444       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04445       if (res < 0) {
04446          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04447       }
04448    } else
04449       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04450 
04451    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04452       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04453       dahdi_close_sub(p, x);
04454       p->subs[x].dfd = -1;
04455       return -1;
04456    }
04457    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04458    return 0;
04459 }

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

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

01558 {
01559    switch (signalling) {
01560    case SIG_FXOLS:
01561    case SIG_FXOGS:
01562    case SIG_FXOKS:
01563    case SIG_FXSLS:
01564    case SIG_FXSGS:
01565    case SIG_FXSKS:
01566    case SIG_EMWINK:
01567    case SIG_EM:
01568    case SIG_EM_E1:
01569    case SIG_FEATD:
01570    case SIG_FEATDMF:
01571    case SIG_E911:
01572    case SIG_FGC_CAMA:
01573    case SIG_FGC_CAMAMF:
01574    case SIG_FEATB:
01575    case SIG_SFWINK:
01576    case SIG_SF:
01577    case SIG_SF_FEATD:
01578    case SIG_SF_FEATDMF:
01579    case SIG_FEATDMF_TA:
01580    case SIG_SF_FEATB:
01581       break;
01582    default:
01583       /* The rest of the function should cover the remainder of signalling types */
01584       return 0;
01585    }
01586 
01587    if (radio) {
01588       return 0;
01589    }
01590 
01591    if (oprmode) {
01592       return 0;
01593    }
01594 
01595    return 1;
01596 }

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

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

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

static int analog_tone_to_dahditone ( enum analog_tone  tone  )  [static]

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

01650 {
01651    switch (tone) {
01652    case ANALOG_TONE_RINGTONE:
01653       return DAHDI_TONE_RINGTONE;
01654    case ANALOG_TONE_STUTTER:
01655       return DAHDI_TONE_STUTTER;
01656    case ANALOG_TONE_CONGESTION:
01657       return DAHDI_TONE_CONGESTION;
01658    case ANALOG_TONE_DIALTONE:
01659       return DAHDI_TONE_DIALTONE;
01660    case ANALOG_TONE_DIALRECALL:
01661       return DAHDI_TONE_DIALRECALL;
01662    case ANALOG_TONE_INFO:
01663       return DAHDI_TONE_INFO;
01664    default:
01665       return -1;
01666    }
01667 }

static int analogsub_to_dahdisub ( enum analog_sub  analogsub  )  [static]

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

01670 {
01671    int index;
01672 
01673    switch (analogsub) {
01674    case ANALOG_SUB_REAL:
01675       index = SUB_REAL;
01676       break;
01677    case ANALOG_SUB_CALLWAIT:
01678       index = SUB_CALLWAIT;
01679       break;
01680    case ANALOG_SUB_THREEWAY:
01681       index = SUB_THREEWAY;
01682       break;
01683    default:
01684       ast_log(LOG_ERROR, "Unidentified sub!\n");
01685       index = SUB_REAL;
01686    }
01687 
01688    return index;
01689 }

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

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

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

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

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

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

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

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

static int bump_gains ( struct dahdi_pvt p  )  [static]

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

05139 {
05140    int res;
05141 
05142    /* Bump receive gain by value stored in cid_rxgain */
05143    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05144    if (res) {
05145       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05146       return -1;
05147    }
05148 
05149    return 0;
05150 }

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

Definition at line 11090 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by do_monitor(), and mwi_thread().

11091 {
11092    int x;
11093    int sum = 0;
11094 
11095    if (!len)
11096       return 0;
11097 
11098    for (x = 0; x < len; x++)
11099       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11100 
11101    return sum / len;
11102 }

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

Definition at line 9912 of file chan_dahdi.c.

References ast_pickup_ext(), and pickup_ext.

Referenced by analog_ss_thread().

09913 {
09914    int extlen = strlen(exten);
09915    const char *pickup_ext;
09916    if (!extlen) {
09917       return 1;
09918    }
09919    pickup_ext = ast_pickup_ext();
09920    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09921       return 1;
09922    }
09923    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09924    if (exten[0] == '*' && extlen < 3) {
09925       if (extlen == 1) {
09926          return 1;
09927       }
09928       /* "*0" should be processed before it gets here */
09929       switch (exten[1]) {
09930       case '6':
09931       case '7':
09932       case '8':
09933          return 1;
09934       }
09935    }
09936    return 0;
09937 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

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

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

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

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

04709 {
04710    /* If the conference already exists, and we're already in it
04711       don't bother doing anything */
04712    struct dahdi_confinfo zi;
04713 
04714    memset(&zi, 0, sizeof(zi));
04715    zi.chan = 0;
04716 
04717    if (slavechannel > 0) {
04718       /* If we have only one slave, do a digital mon */
04719       zi.confmode = DAHDI_CONF_DIGITALMON;
04720       zi.confno = slavechannel;
04721    } else {
04722       if (!idx) {
04723          /* Real-side and pseudo-side both participate in conference */
04724          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04725             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04726       } else
04727          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04728       zi.confno = p->confno;
04729    }
04730    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04731       return 0;
04732    if (c->dfd < 0)
04733       return 0;
04734    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04735       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04736       return -1;
04737    }
04738    if (slavechannel < 1) {
04739       p->confno = zi.confno;
04740    }
04741    c->curconf = zi;
04742    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04743    return 0;
04744 }

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

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

04758 {
04759    struct dahdi_confinfo zi;
04760    if (/* Can't delete if there's no dfd */
04761       (c->dfd < 0) ||
04762       /* Don't delete from the conference if it's not our conference */
04763       !isourconf(p, c)
04764       /* Don't delete if we don't think it's conferenced at all (implied) */
04765       ) return 0;
04766    memset(&zi, 0, sizeof(zi));
04767    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04768       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04769       return -1;
04770    }
04771    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04772    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04773    return 0;
04774 }

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

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

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

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

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

02166 {
02167    char ch_name[20];
02168 
02169    if (p->channel < CHAN_PSEUDO) {
02170       /* No B channel */
02171       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02172    } else if (p->channel == CHAN_PSEUDO) {
02173       /* Pseudo channel */
02174       strcpy(ch_name, "pseudo");
02175    } else {
02176       /* Real channel */
02177       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02178    }
02179    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02180       "Channel: %s\r\n"
02181       "Uniqueid: %s\r\n"
02182       "DAHDISpan: %d\r\n"
02183       "DAHDIChannel: %s\r\n",
02184       chan->name,
02185       chan->uniqueid,
02186       p->span,
02187       ch_name);
02188 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

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

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

static int dahdi_callwait ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

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

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

18520 {
18521    struct dahdi_pvt *tmp;
18522    struct ast_data *data_channel;
18523 
18524    ast_mutex_lock(&iflock);
18525    for (tmp = iflist; tmp; tmp = tmp->next) {
18526       data_channel = ast_data_add_node(data_root, "channel");
18527       if (!data_channel) {
18528          continue;
18529       }
18530 
18531       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18532 
18533       /* if this channel doesn't match remove it. */
18534       if (!ast_data_search_match(search, data_channel)) {
18535          ast_data_remove_node(data_root, data_channel);
18536       }
18537    }
18538    ast_mutex_unlock(&iflock);
18539 
18540    return 0;
18541 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 4390 of file chan_dahdi.c.

Referenced by dahdi_close_sub().

04391 {
04392    if (fd > 0)
04393       close(fd);
04394 }

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

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

04397 {
04398    dahdi_close(chan_pvt->subs[sub_num].dfd);
04399    chan_pvt->subs[sub_num].dfd = -1;
04400 }

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

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

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

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

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

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

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

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

11441 {
11442    struct dahdi_pvt *cur;
11443 
11444    ast_mutex_lock(&iflock);
11445    for (cur = iflist; cur; cur = cur->next) {
11446       if (cur->channel == channel) {
11447          int x = DAHDI_FLASH;
11448 
11449          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11450          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11451 
11452          destroy_channel(cur, 1);
11453          ast_mutex_unlock(&iflock);
11454          ast_module_unref(ast_module_info->self);
11455          return RESULT_SUCCESS;
11456       }
11457    }
11458    ast_mutex_unlock(&iflock);
11459    return RESULT_FAILURE;
11460 }

static int dahdi_devicestate ( void *  data  )  [static]

Definition at line 13856 of file chan_dahdi.c.

References AST_DEVICE_UNKNOWN.

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

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

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

04495 {
04496    struct dahdi_pvt *pvt;
04497    int idx;
04498    int dtmf = -1;
04499    int res;
04500 
04501    pvt = chan->tech_pvt;
04502 
04503    ast_mutex_lock(&pvt->lock);
04504 
04505    idx = dahdi_get_index(chan, pvt, 0);
04506 
04507    if ((idx != SUB_REAL) || !pvt->owner)
04508       goto out;
04509 
04510 #ifdef HAVE_PRI
04511    switch (pvt->sig) {
04512    case SIG_PRI_LIB_HANDLE_CASES:
04513       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04514       if (!res)
04515          goto out;
04516       break;
04517    default:
04518       break;
04519    }
04520 #endif
04521    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04522       goto out;
04523 
04524    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04525       struct dahdi_dialoperation zo = {
04526          .op = DAHDI_DIAL_OP_APPEND,
04527       };
04528 
04529       zo.dialstr[0] = 'T';
04530       zo.dialstr[1] = digit;
04531       zo.dialstr[2] = '\0';
04532       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04533          ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04534             chan->name, digit, strerror(errno));
04535       else
04536          pvt->dialing = 1;
04537    } else {
04538       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04539          chan->name, digit);
04540       pvt->dialing = 1;
04541       pvt->begindigit = digit;
04542    }
04543 
04544 out:
04545    ast_mutex_unlock(&pvt->lock);
04546 
04547    return 0;
04548 }

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

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

04551 {
04552    struct dahdi_pvt *pvt;
04553    int res = 0;
04554    int idx;
04555    int x;
04556 
04557    pvt = chan->tech_pvt;
04558 
04559    ast_mutex_lock(&pvt->lock);
04560 
04561    idx = dahdi_get_index(chan, pvt, 0);
04562 
04563    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04564       goto out;
04565 
04566 #ifdef HAVE_PRI
04567    /* This means that the digit was already sent via PRI signalling */
04568    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04569       goto out;
04570    }
04571 #endif
04572 
04573    if (pvt->begindigit) {
04574       x = -1;
04575       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04576          chan->name, digit);
04577       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04578       pvt->dialing = 0;
04579       pvt->begindigit = 0;
04580    }
04581 
04582 out:
04583    ast_mutex_unlock(&pvt->lock);
04584 
04585    return res;
04586 }

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

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

04963 {
04964    int res;
04965 
04966    if (p->echocanon) {
04967       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04968 
04969       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04970 
04971       if (res)
04972          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04973       else
04974          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04975    }
04976 
04977    p->echocanon = 0;
04978 }

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

09890 {
09891    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09892       return analog_dnd(dahdichan->sig_pvt, flag);
09893    }
09894 
09895    if (flag == -1) {
09896       return dahdichan->dnd;
09897    }
09898 
09899    /* Do not disturb */
09900    dahdichan->dnd = flag;
09901    ast_verb(3, "%s DND on channel %d\n",
09902          flag? "Enabled" : "Disabled",
09903          dahdichan->channel);
09904    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09905          "Channel: DAHDI/%d\r\n"
09906          "Status: %s\r\n", dahdichan->channel,
09907          flag? "enabled" : "disabled");
09908 
09909    return 0;
09910 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

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

04891 {
04892    int res;
04893    if (!p)
04894       return;
04895    if (p->echocanon) {
04896       ast_debug(1, "Echo cancellation already on\n");
04897       return;
04898    }
04899    if (p->digital) {
04900       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04901       return;
04902    }
04903    if (p->echocancel.head.tap_length) {
04904 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04905       switch (p->sig) {
04906 #if defined(HAVE_PRI)
04907       case SIG_PRI_LIB_HANDLE_CASES:
04908          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04909             /*
04910              * PRI nobch pseudo channel.  Does not need ec anyway.
04911              * Does not handle ioctl(DAHDI_AUDIOMODE)
04912              */
04913             return;
04914          }
04915          /* Fall through */
04916 #endif   /* defined(HAVE_PRI) */
04917 #if defined(HAVE_SS7)
04918       case SIG_SS7:
04919 #endif   /* defined(HAVE_SS7) */
04920          {
04921             int x = 1;
04922 
04923             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04924             if (res)
04925                ast_log(LOG_WARNING,
04926                   "Unable to enable audio mode on channel %d (%s)\n",
04927                   p->channel, strerror(errno));
04928          }
04929          break;
04930       default:
04931          break;
04932       }
04933 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04934       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04935       if (res) {
04936          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04937       } else {
04938          p->echocanon = 1;
04939          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04940       }
04941    } else
04942       ast_debug(1, "No echo cancellation requested\n");
04943 }

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

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

08916 {
08917    struct dahdi_pvt *p = ast->tech_pvt;
08918    struct ast_frame *f;
08919    ast_mutex_lock(&p->lock);
08920    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08921       struct analog_pvt *analog_p = p->sig_pvt;
08922       f = analog_exception(analog_p, ast);
08923    } else {
08924       f = __dahdi_exception(ast);
08925    }
08926    ast_mutex_unlock(&p->lock);
08927    return f;
08928 }

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

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

15913 {
15914    if (p) {
15915       switch (mode) {
15916       case TRANSFER:
15917          p->fake_event = DAHDI_EVENT_WINKFLASH;
15918          break;
15919       case HANGUP:
15920          p->fake_event = DAHDI_EVENT_ONHOOK;
15921          break;
15922       default:
15923          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15924       }
15925    }
15926    return 0;
15927 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int dahdi_hangup ( struct ast_channel ast  )  [static]

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

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

static void dahdi_iflist_extract ( struct dahdi_pvt pvt  )  [static]

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

05559 {
05560    /* Extract from the forward chain. */
05561    if (pvt->prev) {
05562       pvt->prev->next = pvt->next;
05563    } else if (iflist == pvt) {
05564       /* Node is at the head of the list. */
05565       iflist = pvt->next;
05566    }
05567 
05568    /* Extract from the reverse chain. */
05569    if (pvt->next) {
05570       pvt->next->prev = pvt->prev;
05571    } else if (ifend == pvt) {
05572       /* Node is at the end of the list. */
05573       ifend = pvt->prev;
05574    }
05575 
05576    /* Node is no longer in the list. */
05577    pvt->which_iflist = DAHDI_IFLIST_NONE;
05578    pvt->prev = NULL;
05579    pvt->next = NULL;
05580 }

static void dahdi_iflist_insert ( struct dahdi_pvt pvt  )  [static]

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

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

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

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

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

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

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

07211                                                                           {
07212    int x;
07213    if (!slave || !master) {
07214       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07215       return;
07216    }
07217    for (x = 0; x < MAX_SLAVES; x++) {
07218       if (!master->slaves[x]) {
07219          master->slaves[x] = slave;
07220          break;
07221       }
07222    }
07223    if (x >= MAX_SLAVES) {
07224       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07225       master->slaves[MAX_SLAVES - 1] = slave;
07226    }
07227    if (slave->master)
07228       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07229    slave->master = master;
07230 
07231    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07232 }

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

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

03807 {
03808    for (;;) {
03809       if (!pvt->subs[sub_idx].owner) {
03810          /* No subchannel owner pointer */
03811          break;
03812       }
03813       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03814          /* Got subchannel owner lock */
03815          break;
03816       }
03817       /* We must unlock the private to avoid the possibility of a deadlock */
03818       DEADLOCK_AVOIDANCE(&pvt->lock);
03819    }
03820 }

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 9622 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_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_digitmode(), ast_dsp_set_features(), 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::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, 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, 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().

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

static int dahdi_open ( char *  fn  )  [static]

Definition at line 4343 of file chan_dahdi.c.

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

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

04344 {
04345    int fd;
04346    int isnum;
04347    int chan = 0;
04348    int bs;
04349    int x;
04350    isnum = 1;
04351    for (x = 0; x < strlen(fn); x++) {
04352       if (!isdigit(fn[x])) {
04353          isnum = 0;
04354          break;
04355       }
04356    }
04357    if (isnum) {
04358       chan = atoi(fn);
04359       if (chan < 1) {
04360          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04361          return -1;
04362       }
04363       fn = "/dev/dahdi/channel";
04364    }
04365    fd = open(fn, O_RDWR | O_NONBLOCK);
04366    if (fd < 0) {
04367       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04368       return -1;
04369    }
04370    if (chan) {
04371       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04372          x = errno;
04373          close(fd);
04374          errno = x;
04375          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04376          return -1;
04377       }
04378    }
04379    bs = READ_SIZE;
04380    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04381       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04382       x = errno;
04383       close(fd);
04384       errno = x;
04385       return -1;
04386    }
04387    return fd;
04388 }

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

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

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

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

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

03832 {
03833    for (;;) {
03834       if (p->owner) {
03835          if (ast_channel_trylock(p->owner)) {
03836             DEADLOCK_AVOIDANCE(&p->lock);
03837          } else {
03838             ast_queue_frame(p->owner, f);
03839             ast_channel_unlock(p->owner);
03840             break;
03841          }
03842       } else
03843          break;
03844    }
03845 }

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

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

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

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

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

static int dahdi_restart ( void   )  [static]

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

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

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

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

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

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

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

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

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

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

05166 {
05167    int x, res;
05168 
05169    x = hs;
05170    res = ioctl(fd, DAHDI_HOOK, &x);
05171 
05172    if (res < 0) {
05173       if (errno == EINPROGRESS)
05174          return 0;
05175       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05176       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05177    }
05178 
05179    return res;
05180 }

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

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

15688 {
15689    int channel;
15690    int gain;
15691    int tx;
15692    struct dahdi_hwgain hwgain;
15693    struct dahdi_pvt *tmp = NULL;
15694 
15695    switch (cmd) {
15696    case CLI_INIT:
15697       e->command = "dahdi set hwgain {rx|tx}";
15698       e->usage =
15699          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15700          "   Sets the hardware gain on a given channel.  Changes take effect\n"
15701          "   immediately whether the channel is in use or not.\n"
15702          "\n"
15703          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15704          "   <chan num> is the channel number relative to the device\n"
15705          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
15706          "\n"
15707          "   Please note:\n"
15708          "   * This is currently the only way to set hwgain by the channel driver.\n"
15709          "   * hwgain is only supportable by hardware with analog ports because\n"
15710          "     hwgain works on the analog side of an analog-digital conversion.\n";
15711       return NULL;
15712    case CLI_GENERATE:
15713       return NULL;
15714    }
15715 
15716    if (a->argc != 6)
15717       return CLI_SHOWUSAGE;
15718 
15719    if (!strcasecmp("rx", a->argv[3]))
15720       tx = 0; /* rx */
15721    else if (!strcasecmp("tx", a->argv[3]))
15722       tx = 1; /* tx */
15723    else
15724       return CLI_SHOWUSAGE;
15725 
15726    channel = atoi(a->argv[4]);
15727    gain = atof(a->argv[5])*10.0;
15728 
15729    ast_mutex_lock(&iflock);
15730 
15731    for (tmp = iflist; tmp; tmp = tmp->next) {
15732 
15733       if (tmp->channel != channel)
15734          continue;
15735 
15736       if (tmp->subs[SUB_REAL].dfd == -1)
15737          break;
15738 
15739       hwgain.newgain = gain;
15740       hwgain.tx = tx;
15741       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15742          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15743          ast_mutex_unlock(&iflock);
15744          return CLI_FAILURE;
15745       }
15746       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15747          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15748       break;
15749    }
15750 
15751    ast_mutex_unlock(&iflock);
15752 
15753    if (tmp)
15754       return CLI_SUCCESS;
15755 
15756    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15757    return CLI_FAILURE;
15758 
15759 }

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

Definition at line 15761 of file chan_dahdi.c.

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

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

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

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

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

Definition at line 15349 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, dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, sig_pri_chan::call, 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, 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.

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

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

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

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

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

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

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

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

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

15655 {
15656    int pseudo_fd = -1;
15657    struct dahdi_versioninfo vi;
15658 
15659    switch (cmd) {
15660    case CLI_INIT:
15661       e->command = "dahdi show version";
15662       e->usage =
15663          "Usage: dahdi show version\n"
15664          "       Shows the DAHDI version in use\n";
15665       return NULL;
15666    case CLI_GENERATE:
15667       return NULL;
15668    }
15669    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15670       ast_cli(a->fd, "Failed to open control file to get version.\n");
15671       return CLI_SUCCESS;
15672    }
15673 
15674    strcpy(vi.version, "Unknown");
15675    strcpy(vi.echo_canceller, "Unknown");
15676 
15677    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15678       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15679    else
15680       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15681 
15682    close(pseudo_fd);
15683 
15684    return CLI_SUCCESS;
15685 }

static char* dahdi_sig2str ( int  sig  )  [static]

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

04643 {
04644    static char buf[256];
04645    switch (sig) {
04646    case SIG_EM:
04647       return "E & M Immediate";
04648    case SIG_EMWINK:
04649       return "E & M Wink";
04650    case SIG_EM_E1:
04651       return "E & M E1";
04652    case SIG_FEATD:
04653       return "Feature Group D (DTMF)";
04654    case SIG_FEATDMF:
04655       return "Feature Group D (MF)";
04656    case SIG_FEATDMF_TA:
04657       return "Feature Groud D (MF) Tandem Access";
04658    case SIG_FEATB:
04659       return "Feature Group B (MF)";
04660    case SIG_E911:
04661       return "E911 (MF)";
04662    case SIG_FGC_CAMA:
04663       return "FGC/CAMA (Dialpulse)";
04664    case SIG_FGC_CAMAMF:
04665       return "FGC/CAMA (MF)";
04666    case SIG_FXSLS:
04667       return "FXS Loopstart";
04668    case SIG_FXSGS:
04669       return "FXS Groundstart";
04670    case SIG_FXSKS:
04671       return "FXS Kewlstart";
04672    case SIG_FXOLS:
04673       return "FXO Loopstart";
04674    case SIG_FXOGS:
04675       return "FXO Groundstart";
04676    case SIG_FXOKS:
04677       return "FXO Kewlstart";
04678    case SIG_PRI:
04679       return "ISDN PRI";
04680    case SIG_BRI:
04681       return "ISDN BRI Point to Point";
04682    case SIG_BRI_PTMP:
04683       return "ISDN BRI Point to MultiPoint";
04684    case SIG_SS7:
04685       return "SS7";
04686    case SIG_MFCR2:
04687       return "MFC/R2";
04688    case SIG_SF:
04689       return "SF (Tone) Immediate";
04690    case SIG_SFWINK:
04691       return "SF (Tone) Wink";
04692    case SIG_SF_FEATD:
04693       return "SF (Tone) with Feature Group D (DTMF)";
04694    case SIG_SF_FEATDMF:
04695       return "SF (Tone) with Feature Group D (MF)";
04696    case SIG_SF_FEATB:
04697       return "SF (Tone) with Feature Group B (MF)";
04698    case 0:
04699       return "Pseudo";
04700    default:
04701       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04702       return buf;
04703    }
04704 }

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

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

01542 {
01543    int handles;
01544 
01545    switch (signaling) {
01546    case SIG_PRI_LIB_HANDLE_CASES:
01547       handles = 1;
01548       break;
01549    default:
01550       handles = 0;
01551       break;
01552    }
01553 
01554    return handles;
01555 }

static void dahdi_softhangup_all ( void   )  [static]

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

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

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

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

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

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

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

04946 {
04947    int x;
04948    int res;
04949 
04950    if (p && p->echocanon && p->echotraining) {
04951       x = p->echotraining;
04952       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04953       if (res)
04954          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04955       else
04956          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04957    } else {
04958       ast_debug(1, "No echo training requested\n");
04959    }
04960 }

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

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

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

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

Definition at line 18550 of file chan_dahdi.c.

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

18552 {
18553    int pseudo_fd = -1;
18554    struct dahdi_versioninfo vi = {
18555       .version = "Unknown",
18556       .echo_canceller = "Unknown"
18557    };
18558 
18559    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18560       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18561       return -1;
18562    }
18563 
18564    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18565       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18566    }
18567 
18568    close(pseudo_fd);
18569 
18570    ast_data_add_str(data_root, "value", vi.version);
18571    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18572 
18573    return 0;
18574 }

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

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

Referenced by analog_ss_thread(), and my_wink().

09863 {
09864    int j;
09865    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09866    for (;;)
09867    {
09868       /* set bits of interest */
09869       j = DAHDI_IOMUX_SIGEVENT;
09870       /* wait for some happening */
09871       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09872       /* exit loop if we have it */
09873       if (j & DAHDI_IOMUX_SIGEVENT) break;
09874    }
09875    /* get the event info */
09876    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09877    return 0;
09878 }

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

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

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

static enum analog_event dahdievent_to_analogevent ( int  event  )  [static]

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

02776 {
02777    enum analog_event res;
02778 
02779    switch (event) {
02780    case DAHDI_EVENT_ONHOOK:
02781       res = ANALOG_EVENT_ONHOOK;
02782       break;
02783    case DAHDI_EVENT_RINGOFFHOOK:
02784       res = ANALOG_EVENT_RINGOFFHOOK;
02785       break;
02786    case DAHDI_EVENT_WINKFLASH:
02787       res = ANALOG_EVENT_WINKFLASH;
02788       break;
02789    case DAHDI_EVENT_ALARM:
02790       res = ANALOG_EVENT_ALARM;
02791       break;
02792    case DAHDI_EVENT_NOALARM:
02793       res = ANALOG_EVENT_NOALARM;
02794       break;
02795    case DAHDI_EVENT_DIALCOMPLETE:
02796       res = ANALOG_EVENT_DIALCOMPLETE;
02797       break;
02798    case DAHDI_EVENT_RINGERON:
02799       res = ANALOG_EVENT_RINGERON;
02800       break;
02801    case DAHDI_EVENT_RINGEROFF:
02802       res = ANALOG_EVENT_RINGEROFF;
02803       break;
02804    case DAHDI_EVENT_HOOKCOMPLETE:
02805       res = ANALOG_EVENT_HOOKCOMPLETE;
02806       break;
02807    case DAHDI_EVENT_PULSE_START:
02808       res = ANALOG_EVENT_PULSE_START;
02809       break;
02810    case DAHDI_EVENT_POLARITY:
02811       res = ANALOG_EVENT_POLARITY;
02812       break;
02813    case DAHDI_EVENT_RINGBEGIN:
02814       res = ANALOG_EVENT_RINGBEGIN;
02815       break;
02816    case DAHDI_EVENT_EC_DISABLED:
02817       res = ANALOG_EVENT_EC_DISABLED;
02818       break;
02819    case DAHDI_EVENT_REMOVED:
02820       res = ANALOG_EVENT_REMOVED;
02821       break;
02822    case DAHDI_EVENT_NEONMWI_ACTIVE:
02823       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02824       break;
02825    case DAHDI_EVENT_NEONMWI_INACTIVE:
02826       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02827       break;
02828 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02829    case DAHDI_EVENT_TX_CED_DETECTED:
02830       res = ANALOG_EVENT_TX_CED_DETECTED;
02831       break;
02832    case DAHDI_EVENT_RX_CED_DETECTED:
02833       res = ANALOG_EVENT_RX_CED_DETECTED;
02834       break;
02835    case DAHDI_EVENT_EC_NLP_DISABLED:
02836       res = ANALOG_EVENT_EC_NLP_DISABLED;
02837       break;
02838    case DAHDI_EVENT_EC_NLP_ENABLED:
02839       res = ANALOG_EVENT_EC_NLP_ENABLED;
02840       break;
02841 #endif
02842    case DAHDI_EVENT_PULSEDIGIT:
02843       res = ANALOG_EVENT_PULSEDIGIT;
02844       break;
02845    case DAHDI_EVENT_DTMFDOWN:
02846       res = ANALOG_EVENT_DTMFDOWN;
02847       break;
02848    case DAHDI_EVENT_DTMFUP:
02849       res = ANALOG_EVENT_DTMFUP;
02850       break;
02851    default:
02852       switch(event & 0xFFFF0000) {
02853       case DAHDI_EVENT_PULSEDIGIT:
02854       case DAHDI_EVENT_DTMFDOWN:
02855       case DAHDI_EVENT_DTMFUP:
02856          /* The event includes a digit number in the low word.
02857           * Converting it to a 'enum analog_event' would remove
02858           * that information. Thus it is returned as-is.
02859           */
02860          return event;
02861       }
02862 
02863       res = ANALOG_EVENT_ERROR;
02864       break;
02865    }
02866 
02867    return res;
02868 }

static enum analog_sigtype dahdisig_to_analogsig ( int  sig  )  [static]

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

01599 {
01600    switch (sig) {
01601    case SIG_FXOLS:
01602       return ANALOG_SIG_FXOLS;
01603    case SIG_FXOGS:
01604       return ANALOG_SIG_FXOGS;
01605    case SIG_FXOKS:
01606       return ANALOG_SIG_FXOKS;
01607    case SIG_FXSLS:
01608       return ANALOG_SIG_FXSLS;
01609    case SIG_FXSGS:
01610       return ANALOG_SIG_FXSGS;
01611    case SIG_FXSKS:
01612       return ANALOG_SIG_FXSKS;
01613    case SIG_EMWINK:
01614       return ANALOG_SIG_EMWINK;
01615    case SIG_EM:
01616       return ANALOG_SIG_EM;
01617    case SIG_EM_E1:
01618       return ANALOG_SIG_EM_E1;
01619    case SIG_FEATD:
01620       return ANALOG_SIG_FEATD;
01621    case SIG_FEATDMF:
01622       return ANALOG_SIG_FEATDMF;
01623    case SIG_E911:
01624       return SIG_E911;
01625    case SIG_FGC_CAMA:
01626       return ANALOG_SIG_FGC_CAMA;
01627    case SIG_FGC_CAMAMF:
01628       return ANALOG_SIG_FGC_CAMAMF;
01629    case SIG_FEATB:
01630       return ANALOG_SIG_FEATB;
01631    case SIG_SFWINK:
01632       return ANALOG_SIG_SFWINK;
01633    case SIG_SF:
01634       return ANALOG_SIG_SF;
01635    case SIG_SF_FEATD:
01636       return ANALOG_SIG_SF_FEATD;
01637    case SIG_SF_FEATDMF:
01638       return ANALOG_SIG_SF_FEATDMF;
01639    case SIG_FEATDMF_TA:
01640       return ANALOG_SIG_FEATDMF_TA;
01641    case SIG_SF_FEATB:
01642       return ANALOG_SIG_FEATB;
01643    default:
01644       return -1;
01645    }
01646 }

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

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

18113 {
18114    struct ast_cc_config_params *cc_params;
18115 
18116    cc_params = dest->chan.cc_params;
18117    *dest = *src;
18118    dest->chan.cc_params = cc_params;
18119    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18120 }

static void destroy_all_channels ( void   )  [static]

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

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

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

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

05823 {
05824    int i;
05825 
05826    if (!now) {
05827       /* Do not destroy the channel now if it is owned by someone. */
05828       if (cur->owner) {
05829          return;
05830       }
05831       for (i = 0; i < 3; i++) {
05832          if (cur->subs[i].owner) {
05833             return;
05834          }
05835       }
05836    }
05837    destroy_dahdi_pvt(cur);
05838 }

static void destroy_dahdi_pvt ( struct dahdi_pvt pvt  )  [static]

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

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

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

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

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

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

Referenced by dahdi_digit_begin().

04479 {
04480    if (isdigit(digit))
04481       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04482    else if (digit >= 'A' && digit <= 'D')
04483       return DAHDI_TONE_DTMF_A + (digit - 'A');
04484    else if (digit >= 'a' && digit <= 'd')
04485       return DAHDI_TONE_DTMF_A + (digit - 'a');
04486    else if (digit == '*')
04487       return DAHDI_TONE_DTMF_s;
04488    else if (digit == '#')
04489       return DAHDI_TONE_DTMF_p;
04490    else
04491       return -1;
04492 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

06652 {
06653    int val = 0;
06654 
06655    p->ignoredtmf = 1;
06656 
06657    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06658 
06659    if (!p->hardwaredtmf && p->dsp) {
06660       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06661       ast_dsp_set_features(p->dsp, p->dsp_features);
06662    }
06663 }

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

Definition at line 11714 of file chan_dahdi.c.

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

Referenced by restart_monitor().

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

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

Definition at line 4981 of file chan_dahdi.c.

Referenced by fill_rxgain(), and fill_txgain().

04982 {
04983    float neg;
04984    float shallow, steep;
04985    float max = SHRT_MAX;
04986    
04987    neg = (sample < 0 ? -1 : 1);
04988    steep = drc*sample;
04989    shallow = neg*(max-max/drc)+(float)sample/drc;
04990    if (abs(steep) < abs(shallow)) {
04991       sample = steep;
04992    }
04993    else {
04994       sample = shallow;
04995    }
04996 
04997    return sample;
04998 }

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

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

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

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

06666 {
06667    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06668 
06669    if (p->channel == CHAN_PSEUDO)
06670       return;
06671 
06672    p->ignoredtmf = 0;
06673 
06674    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06675 
06676    if (!p->hardwaredtmf && p->dsp) {
06677       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06678       ast_dsp_set_features(p->dsp, p->dsp_features);
06679    }
06680 }

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

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

04634 {
04635    static char buf[256];
04636    if ((event < (ARRAY_LEN(events))) && (event > -1))
04637       return events[event];
04638    sprintf(buf, "Event %d", event); /* safe */
04639    return buf;
04640 }

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

Definition at line 5051 of file chan_dahdi.c.

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

Referenced by set_actual_rxgain().

05052 {
05053    int j;
05054    int k;
05055    float linear_gain = pow(10.0, gain / 20.0);
05056 
05057    switch (law) {
05058    case DAHDI_LAW_ALAW:
05059       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05060          if (gain || drc) {
05061             k = AST_ALAW(j);
05062             if (drc) {
05063                k = drc_sample(k, drc);
05064             }
05065             k = (float)k * linear_gain;
05066             if (k > 32767) {
05067                k = 32767;
05068             } else if (k < -32768) {
05069                k = -32768;
05070             }
05071             g->rxgain[j] = AST_LIN2A(k);
05072          } else {
05073             g->rxgain[j] = j;
05074          }
05075       }
05076       break;
05077    case DAHDI_LAW_MULAW:
05078       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05079          if (gain || drc) {
05080             k = AST_MULAW(j);
05081             if (drc) {
05082                k = drc_sample(k, drc);
05083             }
05084             k = (float)k * linear_gain;
05085             if (k > 32767) {
05086                k = 32767;
05087             } else if (k < -32768) {
05088                k = -32768;
05089             }
05090             g->rxgain[j] = AST_LIN2MU(k);
05091          } else {
05092             g->rxgain[j] = j;
05093          }
05094       }
05095       break;
05096    }
05097 }

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

Definition at line 5001 of file chan_dahdi.c.

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

Referenced by set_actual_txgain().

05002 {
05003    int j;
05004    int k;
05005 
05006    float linear_gain = pow(10.0, gain / 20.0);
05007 
05008    switch (law) {
05009    case DAHDI_LAW_ALAW:
05010       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05011          if (gain || drc) {
05012             k = AST_ALAW(j);
05013             if (drc) {
05014                k = drc_sample(k, drc);
05015             }
05016             k = (float)k * linear_gain;
05017             if (k > 32767) {
05018                k = 32767;
05019             } else if (k < -32768) {
05020                k = -32768;
05021             }
05022             g->txgain[j] = AST_LIN2A(k);
05023          } else {
05024             g->txgain[j] = j;
05025          }
05026       }
05027       break;
05028    case DAHDI_LAW_MULAW:
05029       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05030          if (gain || drc) {
05031             k = AST_MULAW(j);
05032             if (drc) {
05033                k = drc_sample(k, drc);
05034             }
05035             k = (float)k * linear_gain;
05036             if (k > 32767) {
05037                k = 32767;
05038             } else if (k < -32768) {
05039                k = -32768;
05040             }
05041             g->txgain[j] = AST_LIN2MU(k);
05042 
05043          } else {
05044             g->txgain[j] = j;
05045          }
05046       }
05047       break;
05048    }
05049 }

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

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

15929 {
15930    struct dahdi_pvt *p;
15931 
15932    ast_mutex_lock(&iflock);
15933    for (p = iflist; p; p = p->next) {
15934       if (p->channel == channel) {
15935          break;
15936       }
15937    }
15938    ast_mutex_unlock(&iflock);
15939    return p;
15940 }

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

Definition at line 15951 of file chan_dahdi.c.

References find_channel().

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

15952 {
15953    int chan_num;
15954 
15955    if (sscanf(channel, "%30d", &chan_num) != 1) {
15956       /* Not numeric string. */
15957       return NULL;
15958    }
15959 
15960    return find_channel(chan_num);
15961 }

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

Definition at line 5741 of file chan_dahdi.c.

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

Referenced by destroy_dahdi_pvt().

05742 {
05743    if (cur->next && cur->next->span == cur->span) {
05744       return cur->next;
05745    } else if (cur->prev && cur->prev->span == cur->span) {
05746       return cur->prev;
05747    }
05748 
05749    return NULL;
05750 }

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

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

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

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

07863 {
07864    const char *alarm_str;
07865 
07866 #if defined(HAVE_PRI)
07867    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07868       return;
07869    }
07870 #endif   /* defined(HAVE_PRI) */
07871 
07872    alarm_str = alarm2str(alms);
07873    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07874       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07875       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07876                  "Alarm: %s\r\n"
07877                  "Channel: %d\r\n",
07878                  alarm_str, p->channel);
07879    }
07880 
07881    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07882       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07883       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07884                  "Alarm: %s\r\n"
07885                  "Span: %d\r\n",
07886                  alarm_str, p->span);
07887    }
07888 }

static void handle_clear_alarms ( struct dahdi_pvt p  )  [static]

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

03848 {
03849 #if defined(HAVE_PRI)
03850    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03851       return;
03852    }
03853 #endif   /* defined(HAVE_PRI) */
03854 
03855    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03856       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03857       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03858    }
03859    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03860       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03861       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03862    }
03863 }

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

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

15535 {
15536    int i, j;
15537    switch (cmd) {
15538    case CLI_INIT:
15539       e->command = "dahdi show cadences";
15540       e->usage =
15541          "Usage: dahdi show cadences\n"
15542          "       Shows all cadences currently defined\n";
15543       return NULL;
15544    case CLI_GENERATE:
15545       return NULL;
15546    }
15547    for (i = 0; i < num_cadence; i++) {
15548       char output[1024];
15549       char tmp[16], tmp2[64];
15550       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15551       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15552 
15553       for (j = 0; j < 16; j++) {
15554          if (cadences[i].ringcadence[j] == 0)
15555             break;
15556          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15557          if (cidrings[i] * 2 - 1 == j)
15558             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15559          else
15560             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15561          if (j != 0)
15562             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15563          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15564       }
15565       ast_cli(a->fd,"%s\n",output);
15566    }
15567    return CLI_SUCCESS;
15568 }

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

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

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

static int has_voicemail ( struct dahdi_pvt p  )  [static]

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

05277 {
05278    int new_msgs;
05279    struct ast_event *event;
05280    char *mailbox, *context;
05281 
05282    mailbox = context = ast_strdupa(p->mailbox);
05283    strsep(&context, "@");
05284    if (ast_strlen_zero(context))
05285       context = "default";
05286 
05287    event = ast_event_get_cached(AST_EVENT_MWI,
05288       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05289       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05290       AST_EVENT_IE_END);
05291 
05292    if (event) {
05293       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05294       ast_event_destroy(event);
05295    } else
05296       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05297 
05298    return new_msgs;
05299 }

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

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

Referenced by dahdi_cc_callback(), and dahdi_request().

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

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

Definition at line 4746 of file chan_dahdi.c.

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

Referenced by conf_del().

04747 {
04748    /* If they're listening to our channel, they're ours */
04749    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04750       return 1;
04751    /* If they're a talker on our (allocated) conference, they're ours */
04752    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04753       return 1;
04754    return 0;
04755 }

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

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

04777 {
04778    int x;
04779    int useslavenative;
04780    struct dahdi_pvt *slave = NULL;
04781    /* Start out optimistic */
04782    useslavenative = 1;
04783    /* Update conference state in a stateless fashion */
04784    for (x = 0; x < 3; x++) {
04785       /* Any three-way calling makes slave native mode *definitely* out
04786          of the question */
04787       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04788          useslavenative = 0;
04789    }
04790    /* If we don't have any 3-way calls, check to see if we have
04791       precisely one slave */
04792    if (useslavenative) {
04793       for (x = 0; x < MAX_SLAVES; x++) {
04794          if (p->slaves[x]) {
04795             if (slave) {
04796                /* Whoops already have a slave!  No
04797                   slave native and stop right away */
04798                slave = NULL;
04799                useslavenative = 0;
04800                break;
04801             } else {
04802                /* We have one slave so far */
04803                slave = p->slaves[x];
04804             }
04805          }
04806       }
04807    }
04808    /* If no slave, slave native definitely out */
04809    if (!slave)
04810       useslavenative = 0;
04811    else if (slave->law != p->law) {
04812       useslavenative = 0;
04813       slave = NULL;
04814    }
04815    if (out)
04816       *out = slave;
04817    return useslavenative;
04818 }

static int load_module ( void   )  [static]

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

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

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::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, 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(), 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(conf);
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          }
12547 #endif
12548 #ifdef HAVE_PRI
12549          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12550             int offset;
12551             int matchesdchan;
12552             int x,y;
12553             int myswitchtype = 0;
12554 
12555             offset = 0;
12556             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12557                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12558                destroy_dahdi_pvt(tmp);
12559                return NULL;
12560             }
12561             if (span >= NUM_SPANS) {
12562                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12563                destroy_dahdi_pvt(tmp);
12564                return NULL;
12565             } else {
12566                si.spanno = 0;
12567                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12568                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12569                   destroy_dahdi_pvt(tmp);
12570                   return NULL;
12571                }
12572                /* Store the logical span first based upon the real span */
12573                tmp->logicalspan = pris[span].prilogicalspan;
12574                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12575                if (span < 0) {
12576                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12577                   destroy_dahdi_pvt(tmp);
12578                   return NULL;
12579                }
12580                myswitchtype = conf->pri.pri.switchtype;
12581                /* Make sure this isn't a d-channel */
12582                matchesdchan=0;
12583                for (x = 0; x < NUM_SPANS; x++) {
12584                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12585                      if (pris[x].dchannels[y] == tmp->channel) {
12586                         matchesdchan = 1;
12587                         break;
12588                      }
12589                   }
12590                }
12591                if (!matchesdchan) {
12592                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12593                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12594                      destroy_dahdi_pvt(tmp);
12595                      return NULL;
12596                   }
12597                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12598                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12599                      destroy_dahdi_pvt(tmp);
12600                      return NULL;
12601                   }
12602                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12603                      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));
12604                      destroy_dahdi_pvt(tmp);
12605                      return NULL;
12606                   }
12607                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12608                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12609                      destroy_dahdi_pvt(tmp);
12610                      return NULL;
12611                   }
12612                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12613                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12614                      destroy_dahdi_pvt(tmp);
12615                      return NULL;
12616                   }
12617                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12618                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12619                      destroy_dahdi_pvt(tmp);
12620                      return NULL;
12621                   }
12622                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12623                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12624                      destroy_dahdi_pvt(tmp);
12625                      return NULL;
12626                   }
12627                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12628                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12629                         pris[span].pri.trunkgroup);
12630                      destroy_dahdi_pvt(tmp);
12631                      return NULL;
12632                   }
12633 
12634                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12635                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12636                   if (!pri_chan) {
12637                      destroy_dahdi_pvt(tmp);
12638                      return NULL;
12639                   }
12640                   tmp->sig_pvt = pri_chan;
12641                   tmp->pri = &pris[span].pri;
12642 
12643                   tmp->priexclusive = conf->chan.priexclusive;
12644 
12645                   if (!tmp->pri->cc_params) {
12646                      tmp->pri->cc_params = ast_cc_config_params_init();
12647                      if (!tmp->pri->cc_params) {
12648                         destroy_dahdi_pvt(tmp);
12649                         return NULL;
12650                      }
12651                   }
12652                   ast_cc_copy_config_params(tmp->pri->cc_params,
12653                      conf->chan.cc_params);
12654 
12655                   pris[span].pri.sig = chan_sig;
12656                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12657                   pris[span].pri.switchtype = myswitchtype;
12658                   pris[span].pri.nsf = conf->pri.pri.nsf;
12659                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12660                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12661                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12662                   pris[span].pri.minunused = conf->pri.pri.minunused;
12663                   pris[span].pri.minidle = conf->pri.pri.minidle;
12664                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12665                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12666                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12667 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12668                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12669 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12670 #ifdef HAVE_PRI_INBANDDISCONNECT
12671                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12672 #endif
12673 #if defined(HAVE_PRI_CALL_HOLD)
12674                   pris[span].pri.hold_disconnect_transfer =
12675                      conf->pri.pri.hold_disconnect_transfer;
12676 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12677 #if defined(HAVE_PRI_CCSS)
12678                   pris[span].pri.cc_ptmp_recall_mode =
12679                      conf->pri.pri.cc_ptmp_recall_mode;
12680                   pris[span].pri.cc_qsig_signaling_link_req =
12681                      conf->pri.pri.cc_qsig_signaling_link_req;
12682                   pris[span].pri.cc_qsig_signaling_link_rsp =
12683                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12684 #endif   /* defined(HAVE_PRI_CCSS) */
12685 #if defined(HAVE_PRI_CALL_WAITING)
12686                   pris[span].pri.max_call_waiting_calls =
12687                      conf->pri.pri.max_call_waiting_calls;
12688                   pris[span].pri.allow_call_waiting_calls =
12689                      conf->pri.pri.allow_call_waiting_calls;
12690 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12691                   pris[span].pri.transfer = conf->chan.transfer;
12692                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12693 #if defined(HAVE_PRI_L2_PERSISTENCE)
12694                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12695 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12696 #if defined(HAVE_PRI_AOC_EVENTS)
12697                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12698                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12699 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12700                   if (chan_sig == SIG_BRI_PTMP) {
12701                      pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12702                   } else {
12703                      /* Option does not apply to this line type. */
12704                      pris[span].pri.layer1_ignored = 0;
12705                   }
12706                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12707                   pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
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->busy_tonelength = conf->chan.busy_tonelength;
12892       tmp->busy_quietlength = conf->chan.busy_quietlength;
12893       tmp->callprogress = conf->chan.callprogress;
12894       tmp->waitfordialtone = conf->chan.waitfordialtone;
12895       tmp->cancallforward = conf->chan.cancallforward;
12896       tmp->dtmfrelax = conf->chan.dtmfrelax;
12897       tmp->callwaiting = tmp->permcallwaiting;
12898       tmp->hidecallerid = tmp->permhidecallerid;
12899       tmp->channel = channel;
12900       tmp->stripmsd = conf->chan.stripmsd;
12901       tmp->use_callerid = conf->chan.use_callerid;
12902       tmp->cid_signalling = conf->chan.cid_signalling;
12903       tmp->cid_start = conf->chan.cid_start;
12904       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12905       tmp->restrictcid = conf->chan.restrictcid;
12906       tmp->use_callingpres = conf->chan.use_callingpres;
12907       if (tmp->usedistinctiveringdetection) {
12908          if (!tmp->use_callerid) {
12909             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12910             tmp->use_callerid = 1;
12911          }
12912       }
12913 
12914       if (tmp->cid_signalling == CID_SIG_SMDI) {
12915          if (!tmp->use_smdi) {
12916             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12917             tmp->use_smdi = 1;
12918          }
12919       }
12920       if (tmp->use_smdi) {
12921          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12922          if (!(tmp->smdi_iface)) {
12923             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12924             tmp->use_smdi = 0;
12925          }
12926       }
12927 
12928       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12929       tmp->amaflags = conf->chan.amaflags;
12930       if (!here) {
12931          tmp->confno = -1;
12932          tmp->propconfno = -1;
12933       }
12934       tmp->canpark = conf->chan.canpark;
12935       tmp->transfer = conf->chan.transfer;
12936       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12937       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12938       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12939       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12940       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12941       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12942       tmp->cid_ton = 0;
12943       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12944          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12945          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12946       } else {
12947          tmp->cid_num[0] = '\0';
12948          tmp->cid_name[0] = '\0';
12949       }
12950 #if defined(HAVE_PRI)
12951       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12952          tmp->cid_tag[0] = '\0';
12953       } else
12954 #endif   /* defined(HAVE_PRI) */
12955       {
12956          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12957       }
12958       tmp->cid_subaddr[0] = '\0';
12959       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12960       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12961          char *mailbox, *context;
12962          mailbox = context = ast_strdupa(tmp->mailbox);
12963          strsep(&context, "@");
12964          if (ast_strlen_zero(context))
12965             context = "default";
12966          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12967             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12968             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12969             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12970             AST_EVENT_IE_END);
12971       }
12972 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12973       tmp->mwisend_setting = conf->chan.mwisend_setting;
12974       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12975       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12976 #endif
12977 
12978       tmp->group = conf->chan.group;
12979       tmp->callgroup = conf->chan.callgroup;
12980       tmp->pickupgroup= conf->chan.pickupgroup;
12981       if (conf->chan.vars) {
12982          struct ast_variable *v, *tmpvar;
12983                    for (v = conf->chan.vars ; v ; v = v->next) {
12984                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12985                                   tmpvar->next = tmp->vars;
12986                                    tmp->vars = tmpvar;
12987                            }
12988                   }
12989       }
12990       tmp->cid_rxgain = conf->chan.cid_rxgain;
12991       tmp->rxgain = conf->chan.rxgain;
12992       tmp->txgain = conf->chan.txgain;
12993       tmp->txdrc = conf->chan.txdrc;
12994       tmp->rxdrc = conf->chan.rxdrc;
12995       tmp->tonezone = conf->chan.tonezone;
12996       if (tmp->subs[SUB_REAL].dfd > -1) {
12997          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12998          if (tmp->dsp)
12999             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13000          update_conf(tmp);
13001          if (!here) {
13002             switch (chan_sig) {
13003             case SIG_PRI_LIB_HANDLE_CASES:
13004             case SIG_SS7:
13005             case SIG_MFCR2:
13006                break;
13007             default:
13008                /* Hang it up to be sure it's good */
13009                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13010                break;
13011             }
13012          }
13013          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13014          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13015             /* the dchannel is down so put the channel in alarm */
13016             switch (tmp->sig) {
13017 #ifdef HAVE_PRI
13018             case SIG_PRI_LIB_HANDLE_CASES:
13019                sig_pri_set_alarm(tmp->sig_pvt, 1);
13020                break;
13021 #endif
13022 #if defined(HAVE_SS7)
13023             case SIG_SS7:
13024                sig_ss7_set_alarm(tmp->sig_pvt, 1);
13025                break;
13026 #endif   /* defined(HAVE_SS7) */
13027             default:
13028                /* The only sig submodule left should be sig_analog. */
13029                analog_p = tmp->sig_pvt;
13030                if (analog_p) {
13031                   analog_p->inalarm = 1;
13032                }
13033                tmp->inalarm = 1;
13034                break;
13035             }
13036             handle_alarms(tmp, res);
13037          }
13038       }
13039 
13040       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13041       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13042       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13043       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13044       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13045 
13046       if (!here) {
13047          tmp->locallyblocked = 0;
13048          tmp->remotelyblocked = 0;
13049          switch (tmp->sig) {
13050 #if defined(HAVE_PRI)
13051          case SIG_PRI_LIB_HANDLE_CASES:
13052             tmp->inservice = 1;/* Inservice until actually implemented. */
13053 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13054             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13055             if (chan_sig == SIG_PRI) {
13056                char db_chan_name[20];
13057                char db_answer[5];
13058 
13059                /*
13060                 * Initialize the active out-of-service status
13061                 * and delete any record if the feature is not enabled.
13062                 */
13063                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13064                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13065                   unsigned *why;
13066 
13067                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13068                   if (tmp->pri->enable_service_message_support) {
13069                      char state;
13070 
13071                      sscanf(db_answer, "%1c:%30u", &state, why);
13072 
13073                      /* Ensure that only the implemented bits could be set.*/
13074                      *why &= (SRVST_NEAREND | SRVST_FAREND);
13075                   }
13076                   if (!*why) {
13077                      ast_db_del(db_chan_name, SRVST_DBKEY);
13078                   }
13079                }
13080             }
13081 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13082             break;
13083 #endif   /* defined(HAVE_PRI) */
13084 #if defined(HAVE_SS7)
13085          case SIG_SS7:
13086             tmp->inservice = 0;
13087             break;
13088 #endif   /* defined(HAVE_SS7) */
13089          default:
13090              /* We default to in service on protocols that don't have a reset */
13091             tmp->inservice = 1;
13092             break;
13093          }
13094       }
13095 
13096       switch (tmp->sig) {
13097 #if defined(HAVE_PRI)
13098       case SIG_PRI_LIB_HANDLE_CASES:
13099          if (pri_chan) {
13100             pri_chan->channel = tmp->channel;
13101             pri_chan->hidecallerid = tmp->hidecallerid;
13102             pri_chan->hidecalleridname = tmp->hidecalleridname;
13103             pri_chan->immediate = tmp->immediate;
13104             pri_chan->inalarm = tmp->inalarm;
13105             pri_chan->priexclusive = tmp->priexclusive;
13106             pri_chan->priindication_oob = tmp->priindication_oob;
13107             pri_chan->use_callerid = tmp->use_callerid;
13108             pri_chan->use_callingpres = tmp->use_callingpres;
13109             ast_copy_string(pri_chan->context, tmp->context,
13110                sizeof(pri_chan->context));
13111             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13112                sizeof(pri_chan->mohinterpret));
13113             pri_chan->stripmsd = tmp->stripmsd;
13114          }
13115          break;
13116 #endif   /* defined(HAVE_PRI) */
13117 #if defined(HAVE_SS7)
13118       case SIG_SS7:
13119          if (ss7_chan) {
13120             ss7_chan->inalarm = tmp->inalarm;
13121 
13122             ss7_chan->stripmsd = tmp->stripmsd;
13123             ss7_chan->hidecallerid = tmp->hidecallerid;
13124             ss7_chan->use_callerid = tmp->use_callerid;
13125             ss7_chan->use_callingpres = tmp->use_callingpres;
13126             ss7_chan->immediate = tmp->immediate;
13127             ss7_chan->locallyblocked = tmp->locallyblocked;
13128             ss7_chan->remotelyblocked = tmp->remotelyblocked;
13129             ast_copy_string(ss7_chan->context, tmp->context,
13130                sizeof(ss7_chan->context));
13131             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13132                sizeof(ss7_chan->mohinterpret));
13133          }
13134          break;
13135 #endif   /* defined(HAVE_SS7) */
13136       default:
13137          /* The only sig submodule left should be sig_analog. */
13138          analog_p = tmp->sig_pvt;
13139          if (analog_p) {
13140             analog_p->channel = tmp->channel;
13141             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13142             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13143             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13144             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13145             analog_p->callreturn = conf->chan.callreturn;
13146             analog_p->cancallforward = conf->chan.cancallforward;
13147             analog_p->canpark = conf->chan.canpark;
13148             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13149             analog_p->immediate = conf->chan.immediate;
13150             analog_p->permhidecallerid = conf->chan.permhidecallerid;
13151             analog_p->pulse = conf->chan.pulse;
13152             analog_p->threewaycalling = conf->chan.threewaycalling;
13153             analog_p->transfer = conf->chan.transfer;
13154             analog_p->transfertobusy = conf->chan.transfertobusy;
13155             analog_p->use_callerid = tmp->use_callerid;
13156             analog_p->use_smdi = tmp->use_smdi;
13157             analog_p->smdi_iface = tmp->smdi_iface;
13158             analog_p->outsigmod = ANALOG_SIG_NONE;
13159             analog_p->echotraining = conf->chan.echotraining;
13160             analog_p->cid_signalling = conf->chan.cid_signalling;
13161             analog_p->stripmsd = conf->chan.stripmsd;
13162             switch (conf->chan.cid_start) {
13163             case CID_START_POLARITY:
13164                analog_p->cid_start = ANALOG_CID_START_POLARITY;
13165                break;
13166             case CID_START_POLARITY_IN:
13167                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13168                break;
13169             case CID_START_DTMF_NOALERT:
13170                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13171                break;
13172             default:
13173                analog_p->cid_start = ANALOG_CID_START_RING;
13174                break;
13175             }
13176             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13177             analog_p->ringt = conf->chan.ringt;
13178             analog_p->ringt_base = ringt_base;
13179             analog_p->onhooktime = time(NULL);
13180             if (chan_sig & __DAHDI_SIG_FXO) {
13181                memset(&p, 0, sizeof(p));
13182                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13183                if (!res) {
13184                   analog_p->fxsoffhookstate = p.rxisoffhook;
13185                }
13186 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13187                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13188 #endif
13189             }
13190             analog_p->msgstate = -1;
13191 
13192             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13193             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13194             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13195 
13196             analog_config_complete(analog_p);
13197          }
13198          break;
13199       }
13200 #if defined(HAVE_PRI)
13201       if (tmp->channel == CHAN_PSEUDO) {
13202          /*
13203           * Save off pseudo channel buffer policy values for dynamic creation of
13204           * no B channel interfaces.
13205           */
13206          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13207          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13208          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13209          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13210       }
13211 #endif   /* defined(HAVE_PRI) */
13212    }
13213    if (tmp && !here) {
13214       /* Add the new channel interface to the sorted channel interface list. */
13215       dahdi_iflist_insert(tmp);
13216    }
13217    return tmp;
13218 }

static void monitor_pfds_clean ( void *  arg  )  [static]

Definition at line 11709 of file chan_dahdi.c.

References ast_free.

Referenced by do_monitor().

11709                                           {
11710    struct pollfd **pfds = arg;
11711    ast_free(*pfds);
11712 }

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

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

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

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

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

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

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

11397 {
11398    int handled = 0;
11399 
11400    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11401       switch (event) {
11402       case DAHDI_EVENT_RINGEROFF:
11403          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11404             handled = 1;
11405 
11406             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11407                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11408                ast_free(pvt->cidspill);
11409                pvt->cidspill = NULL;
11410                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11411                pvt->mwisendactive = 0;
11412             } else {
11413                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11414                gettimeofday(&pvt->mwisend_data.pause, NULL);
11415             }
11416          }
11417          break;
11418       /* Going off hook, I need to punt this spill */
11419       case DAHDI_EVENT_RINGOFFHOOK:
11420          if (pvt->cidspill) {
11421             ast_free(pvt->cidspill);
11422             pvt->cidspill = NULL;
11423             pvt->cidpos = 0;
11424             pvt->cidlen = 0;
11425          }
11426          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11427          pvt->mwisendactive = 0;
11428          break;
11429       case DAHDI_EVENT_RINGERON:
11430       case DAHDI_EVENT_HOOKCOMPLETE:
11431          break;
11432       default:
11433          break;
11434       }
11435    }
11436    return handled;
11437 }

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

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

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

static void my_all_subchannels_hungup ( void *  pvt  )  [static]

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

02439 {
02440    struct dahdi_pvt *p = pvt;
02441    int res, law;
02442 
02443    p->faxhandled = 0;
02444    p->didtdd = 0;
02445 
02446    if (p->dsp) {
02447       ast_dsp_free(p->dsp);
02448       p->dsp = NULL;
02449    }
02450 
02451    p->law = p->law_default;
02452    law = p->law_default;
02453    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02454    if (res < 0)
02455       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02456 
02457    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02458 
02459 #if 1
02460    {
02461    int i;
02462    p->owner = NULL;
02463    /* Cleanup owners here */
02464    for (i = 0; i < 3; i++) {
02465       p->subs[i].owner = NULL;
02466    }
02467    }
02468 #endif
02469 
02470    reset_conf(p);
02471    if (num_restart_pending == 0) {
02472       restart_monitor();
02473    }
02474 }

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

Definition at line 2749 of file chan_dahdi.c.

References alloc_sub(), and analogsub_to_dahdisub().

02750 {
02751    struct dahdi_pvt *p = pvt;
02752 
02753    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02754 }

static void my_answer_polarityswitch ( void *  pvt  )  [static]

Definition at line 2987 of file chan_dahdi.c.

References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().

02988 {
02989    struct dahdi_pvt *p = pvt;
02990 
02991    if (!p->answeronpolarityswitch) {
02992       return;
02993    }
02994 
02995    my_set_polarity(pvt, 1);
02996 }

static int my_callwait ( void *  pvt  )  [static]

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

01931 {
01932    struct dahdi_pvt *p = pvt;
01933    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01934    if (p->cidspill) {
01935       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01936       ast_free(p->cidspill);
01937    }
01938 
01939    /*
01940     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01941     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01942     */
01943    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01944       return -1;
01945    save_conference(p);
01946    /* Silence */
01947    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01948    if (!p->callwaitrings && p->callwaitingcallerid) {
01949       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01950       p->callwaitcas = 1;
01951       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01952    } else {
01953       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01954       p->callwaitcas = 0;
01955       p->cidlen = 2400 + READ_SIZE * 4;
01956    }
01957    p->cidpos = 0;
01958    send_callerid(p);
01959 
01960    return 0;
01961 }

static void my_cancel_cidspill ( void *  pvt  )  [static]

Definition at line 2388 of file chan_dahdi.c.

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

02389 {
02390    struct dahdi_pvt *p = pvt;
02391 
02392    ast_free(p->cidspill);
02393    p->cidspill = NULL;
02394    restore_conference(p);
02395 }

static int my_check_confirmanswer ( void *  pvt  )  [static]

Definition at line 2371 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

02372 {
02373    struct dahdi_pvt *p = pvt;
02374    if (p->confirmanswer) {
02375       return 1;
02376    }
02377 
02378    return 0;
02379 }

static int my_check_for_conference ( void *  pvt  )  [static]

Definition at line 2548 of file chan_dahdi.c.

References check_for_conference().

02549 {
02550    struct dahdi_pvt *p = pvt;
02551    return check_for_conference(p);
02552 }

static int my_check_waitingfordt ( void *  pvt  )  [static]

Definition at line 2354 of file chan_dahdi.c.

References dahdi_pvt::waitingfordt.

02355 {
02356    struct dahdi_pvt *p = pvt;
02357 
02358    if (p->waitingfordt.tv_usec) {
02359       return 1;
02360    }
02361 
02362    return 0;
02363 }

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

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

02499 {
02500    struct dahdi_pvt *p = pvt;
02501    int needconf = needconference;
02502    int x;
02503    int useslavenative;
02504    struct dahdi_pvt *slave = NULL;
02505 
02506    useslavenative = isslavenative(p, &slave);
02507 
02508    /* If we have a slave, add him to our conference now. or DAX
02509       if this is slave native */
02510    for (x = 0; x < MAX_SLAVES; x++) {
02511       if (p->slaves[x]) {
02512          if (useslavenative)
02513             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02514          else {
02515             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02516             needconf++;
02517          }
02518       }
02519    }
02520    /* If we're supposed to be in there, do so now */
02521    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02522       if (useslavenative)
02523          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02524       else {
02525          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02526          needconf++;
02527       }
02528    }
02529    /* If we have a master, add ourselves to his conference */
02530    if (p->master) {
02531       if (isslavenative(p->master, NULL)) {
02532          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02533       } else {
02534          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02535       }
02536    }
02537    if (!needconf) {
02538       /* Nobody is left (or should be left) in our conference.
02539          Kill it. */
02540       p->confno = -1;
02541    }
02542 
02543    return 0;
02544 }

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

Definition at line 2488 of file chan_dahdi.c.

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

02489 {
02490    struct dahdi_pvt *p = pvt;
02491    int x = analogsub_to_dahdisub(sub);
02492 
02493    return conf_add(p, &p->subs[x], x, 0);
02494 }

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

Definition at line 2478 of file chan_dahdi.c.

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

02479 {
02480    struct dahdi_pvt *p = pvt;
02481    int x = analogsub_to_dahdisub(sub);
02482 
02483    return conf_del(p, &p->subs[x], x);
02484 }

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

Definition at line 2397 of file chan_dahdi.c.

References dahdi_confmute().

02398 {
02399    struct dahdi_pvt *p = pvt;
02400    return dahdi_confmute(p, mute);
02401 }

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

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

09367 {
09368    int sent=0;
09369    int size;
09370    int res;
09371    int fd;
09372    fd = p->subs[idx].dfd;
09373    while (len) {
09374       size = len;
09375       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09376          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09377       res = write(fd, buf, size);
09378       if (res != size) {
09379          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09380          return sent;
09381       }
09382       len -= size;
09383       buf += size;
09384    }
09385    return sent;
09386 }

static void my_deadlock_avoidance_private ( void *  pvt  )  [static]

Definition at line 2148 of file chan_dahdi.c.

References DEADLOCK_AVOIDANCE, and dahdi_pvt::lock.

02149 {
02150    struct dahdi_pvt *p = pvt;
02151 
02152    DEADLOCK_AVOIDANCE(&p->lock);
02153 }

static void my_decrease_ss_count ( void   )  [static]

Definition at line 2430 of file chan_dahdi.c.

References ast_cond_signal, ast_mutex_lock, and ast_mutex_unlock.

02431 {
02432    ast_mutex_lock(&ss_thread_lock);
02433    ss_thread_count--;
02434    ast_cond_signal(&ss_thread_complete);
02435    ast_mutex_unlock(&ss_thread_lock);
02436 }

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

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

03022 {
03023    int index = analogsub_to_dahdisub(sub);
03024    int res;
03025    struct dahdi_pvt *p = pvt;
03026    struct dahdi_dialoperation ddop;
03027 
03028    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03029       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03030       return -1;
03031    }
03032 
03033    if (sub != ANALOG_SUB_REAL) {
03034       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03035          dop->dialstr, p->channel, sub);
03036       return -1;
03037    }
03038 
03039    ddop.op = DAHDI_DIAL_OP_REPLACE;
03040    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03041 
03042    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03043 
03044    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03045    if (res == -1) {
03046       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03047    }
03048 
03049    return res;
03050 }

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

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

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

static int my_dsp_reset_and_flush_digits ( void *  pvt  )  [static]

Definition at line 1998 of file chan_dahdi.c.

References ast_dsp_digitreset(), and dahdi_pvt::dsp.

01999 {
02000    struct dahdi_pvt *p = pvt;
02001    if (p->dsp)
02002       ast_dsp_digitreset(p->dsp);
02003 
02004    return 0;
02005 }

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

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

02008 {
02009    struct dahdi_pvt *p = pvt;
02010 
02011    if (p->channel == CHAN_PSEUDO)
02012       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02013 
02014    if (mode == ANALOG_DIGITMODE_DTMF) {
02015       /* If we do hardware dtmf, no need for a DSP */
02016       if (p->hardwaredtmf) {
02017          if (p->dsp) {
02018             ast_dsp_free(p->dsp);
02019             p->dsp = NULL;
02020          }
02021          return 0;
02022       }
02023 
02024       if (!p->dsp) {
02025          p->dsp = ast_dsp_new();
02026          if (!p->dsp) {
02027             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02028             return -1;
02029          }
02030       }
02031 
02032       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02033    } else if (mode == ANALOG_DIGITMODE_MF) {
02034       if (!p->dsp) {
02035          p->dsp = ast_dsp_new();
02036          if (!p->dsp) {
02037             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02038             return -1;
02039          }
02040       }
02041       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02042    }
02043    return 0;
02044 }

static int my_flash ( void *  pvt  )  [static]

Definition at line 2946 of file chan_dahdi.c.

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

02947 {
02948    struct dahdi_pvt *p = pvt;
02949    int func = DAHDI_FLASH;
02950    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02951 }

static void my_get_and_handle_alarms ( void *  pvt  )  [static]

Definition at line 2234 of file chan_dahdi.c.

References get_alarms(), and handle_alarms().

02235 {
02236    int res;
02237    struct dahdi_pvt *p = pvt;
02238 
02239    res = get_alarms(p);
02240    handle_alarms(p, res);
02241 }

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

Definition at line 1720 of file chan_dahdi.c.

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

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

static int my_get_event ( void *  pvt  )  [static]

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

02880 {
02881    struct dahdi_pvt *p = pvt;
02882    int res;
02883 
02884    if (p->fake_event) {
02885       res = p->fake_event;
02886       p->fake_event = 0;
02887    } else
02888       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02889 
02890    return dahdievent_to_analogevent(res);
02891 }

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

Definition at line 2416 of file chan_dahdi.c.

References dahdi_pvt::dialstring.

02417 {
02418    struct dahdi_pvt *p = pvt;
02419 
02420    return p->dialstring;
02421 }

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

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

02244 {
02245    struct ast_channel *bridged = ast_bridged_channel(chan);
02246 
02247    if (bridged && bridged->tech == &dahdi_tech) {
02248       struct dahdi_pvt *p = bridged->tech_pvt;
02249 
02250       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02251          return p->sig_pvt;
02252       }
02253    }
02254    return NULL;
02255 }

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

Definition at line 2257 of file chan_dahdi.c.

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

02258 {
02259    struct dahdi_pvt *p = pvt;
02260    int dahdi_sub = analogsub_to_dahdisub(sub);
02261    return p->subs[dahdi_sub].dfd;
02262 }

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

Definition at line 9843 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by analog_ss_thread().

09844 {
09845    char c;
09846 
09847    *str = 0; /* start with empty output buffer */
09848    for (;;)
09849    {
09850       /* Wait for the first digit (up to specified ms). */
09851       c = ast_waitfordigit(chan, ms);
09852       /* if timeout, hangup or error, return as such */
09853       if (c < 1)
09854          return c;
09855       *str++ = c;
09856       *str = 0;
09857       if (strchr(term, c))
09858          return 1;
09859    }
09860 }

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

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

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

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

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

03664 {
03665    struct dahdi_pvt *p = pvt;
03666 
03667    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03668       return;
03669 
03670    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03671       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03672       notify_message(p->mailbox, 1);
03673    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03674       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03675       notify_message(p->mailbox, 0);
03676    }
03677    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03678    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03679    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03680       ast_hangup(chan);
03681       return;
03682    }
03683 }

static void my_hangup_polarityswitch ( void *  pvt  )  [static]

Definition at line 2998 of file chan_dahdi.c.

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

02999 {
03000    struct dahdi_pvt *p = pvt;
03001 
03002    if (!p->hanguponpolarityswitch) {
03003       return;
03004    }
03005 
03006    if (p->answeronpolarityswitch) {
03007       my_set_polarity(pvt, 0);
03008    } else {
03009       my_set_polarity(pvt, 1);
03010    }
03011 }

static int my_has_voicemail ( void *  pvt  )  [static]

Definition at line 2758 of file chan_dahdi.c.

References has_voicemail().

02759 {
02760    struct dahdi_pvt *p = pvt;
02761 
02762    return has_voicemail(p);
02763 }

static int my_have_progressdetect ( void *  pvt  )  [static]

Definition at line 3685 of file chan_dahdi.c.

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

03686 {
03687    struct dahdi_pvt *p = pvt;
03688 
03689    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03690       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03691       return 1;
03692    } else {
03693       /* Don't have progress detection. */
03694       return 0;
03695    }
03696 }

static void my_increase_ss_count ( void   )  [static]

Definition at line 2423 of file chan_dahdi.c.

References ast_mutex_lock, and ast_mutex_unlock.

02424 {
02425    ast_mutex_lock(&ss_thread_lock);
02426    ss_thread_count++;
02427    ast_mutex_unlock(&ss_thread_lock);
02428 }

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

Definition at line 3063 of file chan_dahdi.c.

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

03064 {
03065    struct dahdi_pvt *p = pvt;
03066    int index;
03067    int x;
03068 
03069    index = analogsub_to_dahdisub(sub);
03070 
03071    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03072       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03073       return -1;
03074    }
03075 
03076    return x;
03077 }

static int my_is_off_hook ( void *  pvt  )  [static]

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

02894 {
02895    struct dahdi_pvt *p = pvt;
02896    int res;
02897    struct dahdi_params par;
02898 
02899    memset(&par, 0, sizeof(par));
02900 
02901    if (p->subs[SUB_REAL].dfd > -1)
02902       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02903    else {
02904       /* Assume not off hook on CVRS */
02905       res = 0;
02906       par.rxisoffhook = 0;
02907    }
02908    if (res) {
02909       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02910    }
02911 
02912    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02913       /* When "onhook" that means no battery on the line, and thus
02914       it is out of service..., if it's on a TDM card... If it's a channel
02915       bank, there is no telling... */
02916       return (par.rxbits > -1) || par.rxisoffhook;
02917    }
02918 
02919    return par.rxisoffhook;
02920 }

static void my_lock_private ( void *  pvt  )  [static]

Definition at line 2136 of file chan_dahdi.c.

References ast_mutex_lock, and dahdi_pvt::lock.

02137 {
02138    struct dahdi_pvt *p = pvt;
02139    ast_mutex_lock(&p->lock);
02140 }

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

References analogsub_to_dahdisub(), and dahdi_new().

02589 {
02590    struct dahdi_pvt *p = pvt;
02591    int dsub = analogsub_to_dahdisub(sub);
02592 
02593    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02594 }

static int my_off_hook ( void *  pvt  )  [static]

Definition at line 2955 of file chan_dahdi.c.

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

02956 {
02957    struct dahdi_pvt *p = pvt;
02958    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02959 }

static int my_on_hook ( void *  pvt  )  [static]

Definition at line 3079 of file chan_dahdi.c.

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

03080 {
03081    struct dahdi_pvt *p = pvt;
03082    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03083 }

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

Definition at line 2765 of file chan_dahdi.c.

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

02766 {
02767    struct dahdi_pvt *p = pvt;
02768    int index;
02769 
02770    index = analogsub_to_dahdisub(sub);
02771 
02772    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02773 }

static int my_ring ( void *  pvt  )  [static]

Definition at line 2939 of file chan_dahdi.c.

References dahdi_ring_phone().

02940 {
02941    struct dahdi_pvt *p = pvt;
02942 
02943    return dahdi_ring_phone(p);
02944 }

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

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

01964 {
01965    struct dahdi_pvt *p = pvt;
01966 
01967    ast_debug(2, "Starting cid spill\n");
01968 
01969    if (p->cidspill) {
01970       ast_log(LOG_WARNING, "cidspill already exists??\n");
01971       ast_free(p->cidspill);
01972    }
01973 
01974    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01975       if (cwcid == 0) {
01976          p->cidlen = ast_callerid_generate(p->cidspill,
01977             caller->id.name.str,
01978             caller->id.number.str,
01979             AST_LAW(p));
01980       } else {
01981          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01982             caller->id.name.str, caller->id.number.str);
01983          p->callwaitcas = 0;
01984          p->cidcwexpire = 0;
01985          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01986             caller->id.name.str,
01987             caller->id.number.str,
01988             AST_LAW(p));
01989          p->cidlen += READ_SIZE * 4;
01990       }
01991       p->cidpos = 0;
01992       p->cid_suppress_expire = 0;
01993       send_callerid(p);
01994    }
01995    return 0;
01996 }

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

Definition at line 2280 of file chan_dahdi.c.

References dahdi_pvt::inalarm.

02281 {
02282    struct dahdi_pvt *p = pvt;
02283 
02284    p->inalarm = in_alarm;
02285 }

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

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

02265 {
02266    struct dahdi_pvt *p = pvt;
02267 
02268    /* Choose proper cadence */
02269    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02270       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02271          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02272       *cid_rings = cidrings[p->distinctivering - 1];
02273    } else {
02274       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02275          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02276       *cid_rings = p->sendcalleridafter;
02277    }
02278 }

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

Definition at line 2381 of file chan_dahdi.c.

References dahdi_pvt::callwaiting.

02382 {
02383    struct dahdi_pvt *p = pvt;
02384 
02385    p->callwaiting = callwaiting_enable;
02386 }

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

Definition at line 2365 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

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

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

Definition at line 2287 of file chan_dahdi.c.

References dahdi_pvt::dialing.

02288 {
02289    struct dahdi_pvt *p = pvt;
02290 
02291    p->dialing = is_dialing;
02292 }

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

Definition at line 2925 of file chan_dahdi.c.

References dahdi_disable_ec(), and dahdi_enable_ec().

02926 {
02927    struct dahdi_pvt *p = pvt;
02928 
02929    if (enable)
02930       dahdi_enable_ec(p);
02931    else
02932       dahdi_disable_ec(p);
02933 
02934    return 0;
02935 }

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

Definition at line 2224 of file chan_dahdi.c.

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

02225 {
02226    struct dahdi_pvt *p = pvt;
02227    int idx = analogsub_to_dahdisub(sub);
02228 
02229    p->subs[idx].inthreeway = inthreeway;
02230 }

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

Definition at line 2212 of file chan_dahdi.c.

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

02213 {
02214    struct dahdi_pvt *p = pvt;
02215    int oldval;
02216    int idx = analogsub_to_dahdisub(sub);
02217    
02218    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02219    oldval = p->subs[idx].linear;
02220    p->subs[idx].linear = linear_mode ? 1 : 0;
02221    return oldval;
02222 }

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

Definition at line 2961 of file chan_dahdi.c.

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

02962 {
02963    struct dahdi_pvt *p = pvt;
02964    p->subs[SUB_REAL].needringing = value;
02965 }

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

Definition at line 2409 of file chan_dahdi.c.

References dahdi_pvt::owner.

02410 {
02411    struct dahdi_pvt *p = pvt;
02412 
02413    p->owner = new_owner;
02414 }

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

Definition at line 2294 of file chan_dahdi.c.

References dahdi_pvt::outgoing.

02295 {
02296    struct dahdi_pvt *p = pvt;
02297 
02298    p->outgoing = is_outgoing;
02299 }

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

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

02968 {
02969    struct dahdi_pvt *p = pvt;
02970 
02971    if (p->channel == CHAN_PSEUDO) {
02972       return;
02973    }
02974    p->polarity = value;
02975    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02976 }

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

Definition at line 2403 of file chan_dahdi.c.

References dahdi_pvt::pulsedial.

02404 {
02405    struct dahdi_pvt *p = pvt;
02406    p->pulsedial = flag;
02407 }

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

Definition at line 2337 of file chan_dahdi.c.

References dahdi_pvt::ringt.

02338 {
02339    struct dahdi_pvt *p = pvt;
02340    p->ringt = ringt;
02341 }

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

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

02344 {
02345    struct dahdi_pvt *p = pvt;
02346 
02347    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02348       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02349       gettimeofday(&p->waitingfordt, NULL);
02350       ast_setstate(ast, AST_STATE_OFFHOOK);
02351    }
02352 }

static int my_start ( void *  pvt  )  [static]

Definition at line 3013 of file chan_dahdi.c.

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

03014 {
03015    struct dahdi_pvt *p = pvt;
03016    int x = DAHDI_START;
03017 
03018    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03019 }

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

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

01696 {
01697    struct dahdi_pvt *p = pvt;
01698    int index = SUB_REAL;
01699    p->cs = callerid_new(cid_signalling);
01700    if (!p->cs) {
01701       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01702       return -1;
01703    }
01704    bump_gains(p);
01705    dahdi_setlinear(p->subs[index].dfd, 0);
01706 
01707    return 0;
01708 }

static void my_start_polarityswitch ( void *  pvt  )  [static]

Definition at line 2978 of file chan_dahdi.c.

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

02979 {
02980    struct dahdi_pvt *p = pvt;
02981 
02982    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02983       my_set_polarity(pvt, 0);
02984    }
02985 }

static int my_stop_callwait ( void *  pvt  )  [static]

Definition at line 1916 of file chan_dahdi.c.

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

01917 {
01918    struct dahdi_pvt *p = pvt;
01919    p->callwaitingrepeat = 0;
01920    p->cidcwexpire = 0;
01921    p->cid_suppress_expire = 0;
01922 
01923    return 0;
01924 }

static int my_stop_cid_detect ( void *  pvt  )  [static]

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

01711 {
01712    struct dahdi_pvt *p = pvt;
01713    int index = SUB_REAL;
01714    if (p->cs)
01715       callerid_free(p->cs);
01716    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01717    return 0;
01718 }

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

02555 {
02556    struct dahdi_pvt *p = pvt;
02557    int da, db;
02558    int tchan;
02559    int tinthreeway;
02560 
02561    da = analogsub_to_dahdisub(a);
02562    db = analogsub_to_dahdisub(b);
02563 
02564    tchan = p->subs[da].chan;
02565    p->subs[da].chan = p->subs[db].chan;
02566    p->subs[db].chan = tchan;
02567 
02568    tinthreeway = p->subs[da].inthreeway;
02569    p->subs[da].inthreeway = p->subs[db].inthreeway;
02570    p->subs[db].inthreeway = tinthreeway;
02571 
02572    p->subs[da].owner = ast_a;
02573    p->subs[db].owner = ast_b;
02574 
02575    if (ast_a)
02576       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02577    if (ast_b)
02578       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02579 
02580    wakeup_sub(p, a);
02581    wakeup_sub(p, b);
02582 
02583    return;
02584 }

static int my_train_echocanceller ( void *  pvt  )  [static]

Definition at line 3054 of file chan_dahdi.c.

References dahdi_train_ec().

03055 {
03056    struct dahdi_pvt *p = pvt;
03057 
03058    dahdi_train_ec(p);
03059 
03060    return 0;
03061 }

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

Definition at line 2740 of file chan_dahdi.c.

References analogsub_to_dahdisub(), and unalloc_sub().

02741 {
02742    struct dahdi_pvt *p = pvt;
02743 
02744    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02745 }

static void my_unlock_private ( void *  pvt  )  [static]

Definition at line 2142 of file chan_dahdi.c.

References ast_mutex_unlock, and dahdi_pvt::lock.

02143 {
02144    struct dahdi_pvt *p = pvt;
02145    ast_mutex_unlock(&p->lock);
02146 }

static int my_wait_event ( void *  pvt  )  [static]

Definition at line 2872 of file chan_dahdi.c.

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

02873 {
02874    struct dahdi_pvt *p = pvt;
02875 
02876    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02877 }

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

Definition at line 2048 of file chan_dahdi.c.

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

02049 {
02050    struct dahdi_pvt *p = pvt;
02051    int index = analogsub_to_dahdisub(sub);
02052    if (index != SUB_REAL) {
02053       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02054    }
02055    return dahdi_wink(p, index);
02056 }

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

03635 {
03636    char s[sizeof(mwimonitornotify) + 80];
03637    struct ast_event *event;
03638    char *mailbox, *context;
03639 
03640    /* Strip off @default */
03641    context = mailbox = ast_strdupa(mailbox_full);
03642    strsep(&context, "@");
03643    if (ast_strlen_zero(context))
03644       context = "default";
03645 
03646    if (!(event = ast_event_new(AST_EVENT_MWI,
03647          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03648          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03649          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03650          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03651          AST_EVENT_IE_END))) {
03652       return;
03653    }
03654 
03655    ast_event_queue_and_cache(event);
03656 
03657    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03658       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03659       ast_safe_system(s);
03660    }
03661 }

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

Definition at line 7052 of file chan_dahdi.c.

References ast_log(), and LOG_WARNING.

Referenced by dahdi_func_write(), and process_dahdi().

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

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

Definition at line 16853 of file chan_dahdi.c.

References string_replace().

Referenced by build_channels().

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

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

Definition at line 16996 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::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, 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_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().

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

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

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

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

static int reload ( void   )  [static]

Definition at line 18778 of file chan_dahdi.c.

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

18779 {
18780    int res = 0;
18781 
18782    res = setup_dahdi(1);
18783    if (res) {
18784       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18785       return -1;
18786    }
18787    return 0;
18788 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

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

04821 {
04822    p->confno = -1;
04823    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04824    if (p->subs[SUB_REAL].dfd > -1) {
04825       struct dahdi_confinfo zi;
04826 
04827       memset(&zi, 0, sizeof(zi));
04828       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04829          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04830    }
04831    return 0;
04832 }

static int restart_monitor ( void   )  [static]

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

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

static int restore_conference ( struct dahdi_pvt p  )  [static]

Definition at line 5245 of file chan_dahdi.c.

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

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

05246 {
05247    int res;
05248    if (p->saveconf.confmode) {
05249       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05250       p->saveconf.confmode = 0;
05251       if (res) {
05252          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05253          return -1;
05254       }
05255       ast_debug(1, "Restored conferencing\n");
05256    }
05257    return 0;
05258 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

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

05153 {
05154    int res;
05155 
05156    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05157    if (res) {
05158       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05159       return -1;
05160    }
05161 
05162    return 0;
05163 }

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

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

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

static int save_conference ( struct dahdi_pvt p  )  [static]

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

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

static int send_callerid ( struct dahdi_pvt p  )  [static]

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

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

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

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

05261 {
05262    p->callwaitcas = 0;
05263    p->cidcwexpire = 0;
05264    p->cid_suppress_expire = 0;
05265    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05266       return -1;
05267    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05268    /* Make sure we account for the end */
05269    p->cidlen += READ_SIZE * 4;
05270    p->cidpos = 0;
05271    send_callerid(p);
05272    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05273    return 0;
05274 }

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

Definition at line 5133 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

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

05134 {
05135    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05136 }

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

Definition at line 5116 of file chan_dahdi.c.

References ast_debug, errno, and fill_rxgain().

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

05117 {
05118    struct dahdi_gains g;
05119    int res;
05120 
05121    memset(&g, 0, sizeof(g));
05122    res = ioctl(fd, DAHDI_GETGAINS, &g);
05123    if (res) {
05124       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05125       return res;
05126    }
05127 
05128    fill_rxgain(&g, gain, drc, law);
05129 
05130    return ioctl(fd, DAHDI_SETGAINS, &g);
05131 }

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

Definition at line 5099 of file chan_dahdi.c.

References ast_debug, errno, and fill_txgain().

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

05100 {
05101    struct dahdi_gains g;
05102    int res;
05103 
05104    memset(&g, 0, sizeof(g));
05105    res = ioctl(fd, DAHDI_GETGAINS, &g);
05106    if (res) {
05107       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05108       return res;
05109    }
05110 
05111    fill_txgain(&g, gain, drc, law);
05112 
05113    return ioctl(fd, DAHDI_SETGAINS, &g);
05114 }

static int setup_dahdi ( int  reload  )  [static]

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

18422 {
18423    int res;
18424    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18425    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18426    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18427 
18428    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18429       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18430    } else {
18431       res = -1;
18432    }
18433    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18434    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18435    ast_cc_config_params_destroy(conf.chan.cc_params);
18436 
18437    return res;
18438 }

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

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

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

Referenced by parse_spanchan().

16845 {
16846    for (; *str; str++) {
16847       if (*str == char1) {
16848          *str = char2;
16849       }
16850    }
16851 }

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

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

04316 {
04317    int tchan;
04318    int tinthreeway;
04319    struct ast_channel *towner;
04320 
04321    ast_debug(1, "Swapping %d and %d\n", a, b);
04322 
04323    tchan = p->subs[a].chan;
04324    towner = p->subs[a].owner;
04325    tinthreeway = p->subs[a].inthreeway;
04326 
04327    p->subs[a].chan = p->subs[b].chan;
04328    p->subs[a].owner = p->subs[b].owner;
04329    p->subs[a].inthreeway = p->subs[b].inthreeway;
04330 
04331    p->subs[b].chan = tchan;
04332    p->subs[b].owner = towner;
04333    p->subs[b].inthreeway = tinthreeway;
04334 
04335    if (p->subs[a].owner)
04336       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04337    if (p->subs[b].owner)
04338       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04339    wakeup_sub(p, a);
04340    wakeup_sub(p, b);
04341 }

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

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

04462 {
04463    if (!x) {
04464       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04465       return -1;
04466    }
04467    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04468    dahdi_close_sub(p, x);
04469    p->subs[x].linear = 0;
04470    p->subs[x].chan = 0;
04471    p->subs[x].owner = NULL;
04472    p->subs[x].inthreeway = 0;
04473    p->polarity = POLARITY_IDLE;
04474    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04475    return 0;
04476 }

static int unload_module ( void   )  [static]

Definition at line 16828 of file chan_dahdi.c.

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

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

static int update_conf ( struct dahdi_pvt p  )  [static]

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

04835 {
04836    int needconf = 0;
04837    int x;
04838    int useslavenative;
04839    struct dahdi_pvt *slave = NULL;
04840 
04841    useslavenative = isslavenative(p, &slave);
04842    /* Start with the obvious, general stuff */
04843    for (x = 0; x < 3; x++) {
04844       /* Look for three way calls */
04845       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04846          conf_add(p, &p->subs[x], x, 0);
04847          needconf++;
04848       } else {
04849          conf_del(p, &p->subs[x], x);
04850       }
04851    }
04852    /* If we have a slave, add him to our conference now. or DAX
04853       if this is slave native */
04854    for (x = 0; x < MAX_SLAVES; x++) {
04855       if (p->slaves[x]) {
04856          if (useslavenative)
04857             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04858          else {
04859             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04860             needconf++;
04861          }
04862       }
04863    }
04864    /* If we're supposed to be in there, do so now */
04865    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04866       if (useslavenative)
04867          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04868       else {
04869          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04870          needconf++;
04871       }
04872    }
04873    /* If we have a master, add ourselves to his conference */
04874    if (p->master) {
04875       if (isslavenative(p->master, NULL)) {
04876          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04877       } else {
04878          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04879       }
04880    }
04881    if (!needconf) {
04882       /* Nobody is left (or should be left) in our conference.
04883          Kill it. */
04884       p->confno = -1;
04885    }
04886    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04887    return 0;
04888 }

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

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

03823 {
03824    dahdi_lock_sub_owner(p, a);
03825    if (p->subs[a].owner) {
03826       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03827       ast_channel_unlock(p->subs[a].owner);
03828    }
03829 }


Variable Documentation

int alarm

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

Initial value:

Definition at line 18581 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

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

Initial value:

Definition at line 18576 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 1500 of file chan_dahdi.c.

Initial value:

Definition at line 18586 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 4588 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 1308 of file chan_dahdi.c.

struct dahdi_pvt* iflist = NULL [static]

Main interface list start

Definition at line 1307 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 4612 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 3769 of file chan_dahdi.c.

Definition at line 474 of file chan_dahdi.c.

int ss_thread_count = 0 [static]

Definition at line 477 of file chan_dahdi.c.

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

Definition at line 635 of file chan_dahdi.c.

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

Definition at line 326 of file chan_dahdi.c.

int usedistinctiveringdetection = 0 [static]

Definition at line 431 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 391 of file chan_dahdi.c.


Generated on 3 Apr 2014 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1