Fri Apr 15 20:39:02 2016

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

Referenced by my_complete_conference_update(), and update_conf().

#define HANGUP   1

Definition at line 16009 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 17037 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 17091 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 17093 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 8799 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().

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

static int __unload_module ( void   )  [static]

Definition at line 16831 of file chan_dahdi.c.

References ARRAY_LEN, ast_cc_agent_unregister(), ast_cc_monitor_unregister(), ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy, ast_data_unregister, ast_manager_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), destroy_all_channels(), sig_ss7_linkset::master, sig_pri_span::master, dahdi_pvt::next, dahdi_pvt::owner, sig_pri_stop_pri(), sig_pri_unload(), and SIG_SS7_NUM_DCHANS.

Referenced by load_module(), and unload_module().

16832 {
16833    struct dahdi_pvt *p;
16834 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16835    int i, j;
16836 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16837 
16838 #ifdef HAVE_PRI
16839    for (i = 0; i < NUM_SPANS; i++) {
16840       if (pris[i].pri.master != AST_PTHREADT_NULL) {
16841          pthread_cancel(pris[i].pri.master);
16842          pthread_kill(pris[i].pri.master, SIGURG);
16843       }
16844    }
16845    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16846    ast_unregister_application(dahdi_send_keypad_facility_app);
16847 #ifdef HAVE_PRI_PROG_W_CAUSE
16848    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16849 #endif
16850 #endif
16851 #if defined(HAVE_SS7)
16852    for (i = 0; i < NUM_SPANS; i++) {
16853       if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
16854          pthread_cancel(linksets[i].ss7.master);
16855          pthread_kill(linksets[i].ss7.master, SIGURG);
16856       }
16857    }
16858    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16859 #endif   /* defined(HAVE_SS7) */
16860 #if defined(HAVE_OPENR2)
16861    dahdi_r2_destroy_links();
16862    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16863    ast_unregister_application(dahdi_accept_r2_call_app);
16864 #endif
16865 
16866    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16867    ast_manager_unregister("DAHDIDialOffhook");
16868    ast_manager_unregister("DAHDIHangup");
16869    ast_manager_unregister("DAHDITransfer");
16870    ast_manager_unregister("DAHDIDNDoff");
16871    ast_manager_unregister("DAHDIDNDon");
16872    ast_manager_unregister("DAHDIShowChannels");
16873    ast_manager_unregister("DAHDIRestart");
16874    ast_data_unregister(NULL);
16875    ast_channel_unregister(&dahdi_tech);
16876 
16877    /* Hangup all interfaces if they have an owner */
16878    ast_mutex_lock(&iflock);
16879    for (p = iflist; p; p = p->next) {
16880       if (p->owner)
16881          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16882    }
16883    ast_mutex_unlock(&iflock);
16884 
16885    ast_mutex_lock(&monlock);
16886    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16887       pthread_cancel(monitor_thread);
16888       pthread_kill(monitor_thread, SIGURG);
16889       pthread_join(monitor_thread, NULL);
16890    }
16891    monitor_thread = AST_PTHREADT_STOP;
16892    ast_mutex_unlock(&monlock);
16893 
16894    destroy_all_channels();
16895 
16896 #if defined(HAVE_PRI)
16897    for (i = 0; i < NUM_SPANS; i++) {
16898       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
16899          pthread_join(pris[i].pri.master, NULL);
16900       }
16901       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16902          dahdi_close_pri_fd(&(pris[i]), j);
16903       }
16904       sig_pri_stop_pri(&pris[i].pri);
16905    }
16906 #if defined(HAVE_PRI_CCSS)
16907    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16908    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16909 #endif   /* defined(HAVE_PRI_CCSS) */
16910    sig_pri_unload();
16911 #endif
16912 
16913 #if defined(HAVE_SS7)
16914    for (i = 0; i < NUM_SPANS; i++) {
16915       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
16916          pthread_join(linksets[i].ss7.master, NULL);
16917       }
16918       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16919          dahdi_close_ss7_fd(&(linksets[i]), j);
16920       }
16921    }
16922 #endif   /* defined(HAVE_SS7) */
16923    ast_cond_destroy(&ss_thread_complete);
16924    return 0;
16925 }

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

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

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

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

16147 {
16148    struct dahdi_pvt *p;
16149    const char *channel = astman_get_header(m, "DAHDIChannel");
16150    const char *number = astman_get_header(m, "Number");
16151    int i;
16152 
16153    if (ast_strlen_zero(channel)) {
16154       astman_send_error(s, m, "No channel specified");
16155       return 0;
16156    }
16157    if (ast_strlen_zero(number)) {
16158       astman_send_error(s, m, "No number specified");
16159       return 0;
16160    }
16161    p = find_channel_from_str(channel);
16162    if (!p) {
16163       astman_send_error(s, m, "No such channel");
16164       return 0;
16165    }
16166    if (!p->owner) {
16167       astman_send_error(s, m, "Channel does not have it's owner");
16168       return 0;
16169    }
16170    for (i = 0; i < strlen(number); i++) {
16171       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16172       dahdi_queue_frame(p, &f);
16173    }
16174    astman_send_ack(s, m, "DAHDIDialOffhook");
16175    return 0;
16176 }

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

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

16082 {
16083    struct dahdi_pvt *p;
16084    const char *channel = astman_get_header(m, "DAHDIChannel");
16085 
16086    if (ast_strlen_zero(channel)) {
16087       astman_send_error(s, m, "No channel specified");
16088       return 0;
16089    }
16090    p = find_channel_from_str(channel);
16091    if (!p) {
16092       astman_send_error(s, m, "No such channel");
16093       return 0;
16094    }
16095    dahdi_dnd(p, 0);
16096    astman_send_ack(s, m, "DND Disabled");
16097    return 0;
16098 }

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

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

16063 {
16064    struct dahdi_pvt *p;
16065    const char *channel = astman_get_header(m, "DAHDIChannel");
16066 
16067    if (ast_strlen_zero(channel)) {
16068       astman_send_error(s, m, "No channel specified");
16069       return 0;
16070    }
16071    p = find_channel_from_str(channel);
16072    if (!p) {
16073       astman_send_error(s, m, "No such channel");
16074       return 0;
16075    }
16076    dahdi_dnd(p, 1);
16077    astman_send_ack(s, m, "DND Enabled");
16078    return 0;
16079 }

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

Definition at line 15351 of file chan_dahdi.c.

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

Referenced by load_module().

15352 {
15353    if (dahdi_restart() != 0) {
15354       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15355       return 1;
15356    }
15357    astman_send_ack(s, m, "DAHDIRestart: Success");
15358    return 0;
15359 }

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

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

16179 {
16180    struct dahdi_pvt *tmp = NULL;
16181    const char *id = astman_get_header(m, "ActionID");
16182    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16183    char idText[256] = "";
16184    int channels = 0;
16185    int dahdichanquery;
16186 
16187    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16188       /* Not numeric string. */
16189       dahdichanquery = -1;
16190    }
16191 
16192    astman_send_ack(s, m, "DAHDI channel status will follow");
16193    if (!ast_strlen_zero(id))
16194       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16195 
16196    ast_mutex_lock(&iflock);
16197 
16198    for (tmp = iflist; tmp; tmp = tmp->next) {
16199       if (tmp->channel > 0) {
16200          int alm;
16201 
16202          /* If a specific channel is queried for, only deliver status for that channel */
16203          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16204             continue;
16205 
16206          alm = get_alarms(tmp);
16207          channels++;
16208          if (tmp->owner) {
16209             /* Add data if we have a current call */
16210             astman_append(s,
16211                "Event: DAHDIShowChannels\r\n"
16212                "DAHDIChannel: %d\r\n"
16213                "Channel: %s\r\n"
16214                "Uniqueid: %s\r\n"
16215                "AccountCode: %s\r\n"
16216                "Signalling: %s\r\n"
16217                "SignallingCode: %d\r\n"
16218                "Context: %s\r\n"
16219                "DND: %s\r\n"
16220                "Alarm: %s\r\n"
16221                "%s"
16222                "\r\n",
16223                tmp->channel,
16224                tmp->owner->name,
16225                tmp->owner->uniqueid,
16226                tmp->owner->accountcode,
16227                sig2str(tmp->sig),
16228                tmp->sig,
16229                tmp->context,
16230                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16231                alarm2str(alm), idText);
16232          } else {
16233             astman_append(s,
16234                "Event: DAHDIShowChannels\r\n"
16235                "DAHDIChannel: %d\r\n"
16236                "Signalling: %s\r\n"
16237                "SignallingCode: %d\r\n"
16238                "Context: %s\r\n"
16239                "DND: %s\r\n"
16240                "Alarm: %s\r\n"
16241                "%s"
16242                "\r\n",
16243                tmp->channel, sig2str(tmp->sig), tmp->sig,
16244                tmp->context,
16245                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16246                alarm2str(alm), idText);
16247          }
16248       }
16249    }
16250 
16251    ast_mutex_unlock(&iflock);
16252 
16253    astman_append(s,
16254       "Event: DAHDIShowChannelsComplete\r\n"
16255       "%s"
16256       "Items: %d\r\n"
16257       "\r\n",
16258       idText,
16259       channels);
16260    return 0;
16261 }

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

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

16101 {
16102    struct dahdi_pvt *p;
16103    const char *channel = astman_get_header(m, "DAHDIChannel");
16104 
16105    if (ast_strlen_zero(channel)) {
16106       astman_send_error(s, m, "No channel specified");
16107       return 0;
16108    }
16109    p = find_channel_from_str(channel);
16110    if (!p) {
16111       astman_send_error(s, m, "No such channel");
16112       return 0;
16113    }
16114    if (!analog_lib_handles(p->sig, 0, 0)) {
16115       astman_send_error(s, m, "Channel signaling is not analog");
16116       return 0;
16117    }
16118    dahdi_fake_event(p,TRANSFER);
16119    astman_send_ack(s, m, "DAHDITransfer");
16120    return 0;
16121 }

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

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

16124 {
16125    struct dahdi_pvt *p;
16126    const char *channel = astman_get_header(m, "DAHDIChannel");
16127 
16128    if (ast_strlen_zero(channel)) {
16129       astman_send_error(s, m, "No channel specified");
16130       return 0;
16131    }
16132    p = find_channel_from_str(channel);
16133    if (!p) {
16134       astman_send_error(s, m, "No such channel");
16135       return 0;
16136    }
16137    if (!analog_lib_handles(p->sig, 0, 0)) {
16138       astman_send_error(s, m, "Channel signaling is not analog");
16139       return 0;
16140    }
16141    dahdi_fake_event(p,HANGUP);
16142    astman_send_ack(s, m, "DAHDIHangup");
16143    return 0;
16144 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 4629 of file chan_dahdi.c.

References alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

04630 {
04631    int x;
04632    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04633       if (alarms[x].alarm & alm)
04634          return alarms[x].name;
04635    }
04636    return alm ? "Unknown Alarm" : "No Alarm";
04637 }

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

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

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

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

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

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

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

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

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

static int analog_tone_to_dahditone ( enum analog_tone  tone  )  [static]

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

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

static int analogsub_to_dahdisub ( enum analog_sub  analogsub  )  [static]

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

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

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

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

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

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

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

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

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

16967 {
16968    char *c, *chan;
16969    char *subdir;
16970    int x, start, finish;
16971    struct dahdi_pvt *tmp;
16972 
16973    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16974       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16975       return -1;
16976    }
16977 
16978    c = ast_strdupa(value);
16979    c = parse_spanchan(c, &subdir);
16980 
16981    while ((chan = strsep(&c, ","))) {
16982       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16983          /* Range */
16984       } else if (sscanf(chan, "%30d", &start)) {
16985          /* Just one */
16986          finish = start;
16987       } else if (!strcasecmp(chan, "pseudo")) {
16988          finish = start = CHAN_PSEUDO;
16989          if (found_pseudo)
16990             *found_pseudo = 1;
16991       } else {
16992          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16993          return -1;
16994       }
16995       if (finish < start) {
16996          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16997          x = finish;
16998          finish = start;
16999          start = x;
17000       }
17001 
17002       for (x = start; x <= finish; x++) {
17003          char fn[PATH_MAX];
17004          int real_channel = x;
17005 
17006          if (!ast_strlen_zero(subdir)) {
17007             real_channel = device2chan(subdir, x, fn, sizeof(fn));
17008             if (real_channel < 0) {
17009                if (conf->ignore_failed_channels) {
17010                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
17011                         subdir, x, real_channel);
17012                   continue;
17013                } else {
17014                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
17015                         subdir, x, real_channel);
17016                   return -1;
17017                }
17018             }
17019          }
17020          tmp = mkintf(real_channel, conf, reload);
17021 
17022          if (tmp) {
17023             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
17024          } else {
17025             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17026                   (reload == 1) ? "reconfigure" : "register", value);
17027             return -1;
17028          }
17029       }
17030    }
17031 
17032    return 0;
17033 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

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

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

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

Definition at line 11096 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by do_monitor(), and mwi_thread().

11097 {
11098    int x;
11099    int sum = 0;
11100 
11101    if (!len)
11102       return 0;
11103 
11104    for (x = 0; x < len; x++)
11105       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11106 
11107    return sum / len;
11108 }

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

Definition at line 9918 of file chan_dahdi.c.

References ast_pickup_ext(), and pickup_ext.

Referenced by analog_ss_thread().

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

static int check_for_conference ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int dahdi_answer ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

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

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

static int dahdi_callwait ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

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

18621 {
18622    struct dahdi_pvt *tmp;
18623    struct ast_data *data_channel;
18624 
18625    ast_mutex_lock(&iflock);
18626    for (tmp = iflist; tmp; tmp = tmp->next) {
18627       data_channel = ast_data_add_node(data_root, "channel");
18628       if (!data_channel) {
18629          continue;
18630       }
18631 
18632       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18633 
18634       /* if this channel doesn't match remove it. */
18635       if (!ast_data_search_match(search, data_channel)) {
18636          ast_data_remove_node(data_root, data_channel);
18637       }
18638    }
18639    ast_mutex_unlock(&iflock);
18640 
18641    return 0;
18642 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 4396 of file chan_dahdi.c.

Referenced by dahdi_close_sub().

04397 {
04398    if (fd > 0)
04399       close(fd);
04400 }

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

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

04403 {
04404    dahdi_close(chan_pvt->subs[sub_num].dfd);
04405    chan_pvt->subs[sub_num].dfd = -1;
04406 }

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

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

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

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

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

15166 {
15167    int channel;
15168    int ret;
15169    switch (cmd) {
15170    case CLI_INIT:
15171       e->command = "dahdi destroy channel";
15172       e->usage =
15173          "Usage: dahdi destroy channel <chan num>\n"
15174          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15175       return NULL;
15176    case CLI_GENERATE:
15177       return NULL;
15178    }
15179    if (a->argc != 4)
15180       return CLI_SHOWUSAGE;
15181 
15182    channel = atoi(a->argv[3]);
15183    ret = dahdi_destroy_channel_bynum(channel);
15184    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15185 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

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

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

static int dahdi_devicestate ( void *  data  )  [static]

Definition at line 13863 of file chan_dahdi.c.

References AST_DEVICE_UNKNOWN.

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

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

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

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

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

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

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

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

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

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

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

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

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

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

16012 {
16013    if (p) {
16014       switch (mode) {
16015       case TRANSFER:
16016          p->fake_event = DAHDI_EVENT_WINKFLASH;
16017          break;
16018       case HANGUP:
16019          p->fake_event = DAHDI_EVENT_ONHOOK;
16020          break;
16021       default:
16022          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
16023       }
16024    }
16025    return 0;
16026 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int dahdi_hangup ( struct ast_channel ast  )  [static]

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

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

static void dahdi_iflist_extract ( struct dahdi_pvt pvt  )  [static]

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

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

static void dahdi_iflist_insert ( struct dahdi_pvt pvt  )  [static]

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

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

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

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

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

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

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

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

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

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

03813 {
03814    for (;;) {
03815       if (!pvt->subs[sub_idx].owner) {
03816          /* No subchannel owner pointer */
03817          break;
03818       }
03819       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03820          /* Got subchannel owner lock */
03821          break;
03822       }
03823       /* We must unlock the private to avoid the possibility of a deadlock */
03824       DEADLOCK_AVOIDANCE(&pvt->lock);
03825    }
03826 }

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

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

static int dahdi_open ( char *  fn  )  [static]

Definition at line 4349 of file chan_dahdi.c.

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

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

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

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

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

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

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

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

03838 {
03839    for (;;) {
03840       if (p->owner) {
03841          if (ast_channel_trylock(p->owner)) {
03842             DEADLOCK_AVOIDANCE(&p->lock);
03843          } else {
03844             ast_queue_frame(p->owner, f);
03845             ast_channel_unlock(p->owner);
03846             break;
03847          }
03848       } else
03849          break;
03850    }
03851 }

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

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

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

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

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

static int dahdi_restart ( void   )  [static]

Definition at line 15216 of file chan_dahdi.c.

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

Referenced by action_dahdirestart(), and dahdi_restart_cmd().

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

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

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

15329 {
15330    switch (cmd) {
15331    case CLI_INIT:
15332       e->command = "dahdi restart";
15333       e->usage =
15334          "Usage: dahdi restart\n"
15335          "  Restarts the DAHDI channels: destroys them all and then\n"
15336          "  re-reads them from chan_dahdi.conf.\n"
15337          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15338          "";
15339       return NULL;
15340    case CLI_GENERATE:
15341       return NULL;
15342    }
15343    if (a->argc != 2)
15344       return CLI_SHOWUSAGE;
15345 
15346    if (dahdi_restart() != 0)
15347       return CLI_FAILURE;
15348    return CLI_SUCCESS;
15349 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

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

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

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

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

18780 {
18781 #define  END_SILENCE_LEN 400
18782 #define  HEADER_MS 50
18783 #define  TRAILER_MS 5
18784 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18785 #define  ASCII_BYTES_PER_CHAR 80
18786 
18787    unsigned char *buf,*mybuf;
18788    struct dahdi_pvt *p = c->tech_pvt;
18789    struct pollfd fds[1];
18790    int size,res,fd,len,x;
18791    int bytes=0;
18792    /* Initial carrier (imaginary) */
18793    float cr = 1.0;
18794    float ci = 0.0;
18795    float scont = 0.0;
18796    int idx;
18797 
18798    idx = dahdi_get_index(c, p, 0);
18799    if (idx < 0) {
18800       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18801       return -1;
18802    }
18803    if (!text[0]) return(0); /* if nothing to send, don't */
18804    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18805    if (p->mate)
18806       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18807    else
18808       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18809    if (!buf)
18810       return -1;
18811    mybuf = buf;
18812    if (p->mate) {
18813       int codec = AST_LAW(p);
18814       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18815          PUT_CLID_MARKMS;
18816       }
18817       /* Put actual message */
18818       for (x = 0; text[x]; x++) {
18819          PUT_CLID(text[x]);
18820       }
18821       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18822          PUT_CLID_MARKMS;
18823       }
18824       len = bytes;
18825       buf = mybuf;
18826    } else {
18827       len = tdd_generate(p->tdd, buf, text);
18828       if (len < 1) {
18829          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18830          ast_free(mybuf);
18831          return -1;
18832       }
18833    }
18834    memset(buf + len, 0x7f, END_SILENCE_LEN);
18835    len += END_SILENCE_LEN;
18836    fd = p->subs[idx].dfd;
18837    while (len) {
18838       if (ast_check_hangup(c)) {
18839          ast_free(mybuf);
18840          return -1;
18841       }
18842       size = len;
18843       if (size > READ_SIZE)
18844          size = READ_SIZE;
18845       fds[0].fd = fd;
18846       fds[0].events = POLLOUT | POLLPRI;
18847       fds[0].revents = 0;
18848       res = poll(fds, 1, -1);
18849       if (!res) {
18850          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18851          continue;
18852       }
18853       /* if got exception */
18854       if (fds[0].revents & POLLPRI) {
18855          ast_free(mybuf);
18856          return -1;
18857       }
18858       if (!(fds[0].revents & POLLOUT)) {
18859          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18860          continue;
18861       }
18862       res = write(fd, buf, size);
18863       if (res != size) {
18864          if (res == -1) {
18865             ast_free(mybuf);
18866             return -1;
18867          }
18868          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18869          break;
18870       }
18871       len -= size;
18872       buf += size;
18873    }
18874    ast_free(mybuf);
18875    return(0);
18876 }

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

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

15939 {
15940    int channel;
15941    int on;
15942    struct dahdi_pvt *dahdi_chan = NULL;
15943 
15944    switch (cmd) {
15945    case CLI_INIT:
15946       e->command = "dahdi set dnd";
15947       e->usage =
15948          "Usage: dahdi set dnd <chan#> <on|off>\n"
15949          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15950          "  Changes take effect immediately.\n"
15951          "  <chan num> is the channel number\n"
15952          "  <on|off> Enable or disable DND mode?\n"
15953          ;
15954       return NULL;
15955    case CLI_GENERATE:
15956       return NULL;
15957    }
15958 
15959    if (a->argc != 5)
15960       return CLI_SHOWUSAGE;
15961 
15962    if ((channel = atoi(a->argv[3])) <= 0) {
15963       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15964       return CLI_SHOWUSAGE;
15965    }
15966 
15967    if (ast_true(a->argv[4]))
15968       on = 1;
15969    else if (ast_false(a->argv[4]))
15970       on = 0;
15971    else {
15972       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15973       return CLI_SHOWUSAGE;
15974    }
15975 
15976    ast_mutex_lock(&iflock);
15977    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15978       if (dahdi_chan->channel != channel)
15979          continue;
15980 
15981       /* Found the channel. Actually set it */
15982       dahdi_dnd(dahdi_chan, on);
15983       break;
15984    }
15985    ast_mutex_unlock(&iflock);
15986 
15987    if (!dahdi_chan) {
15988       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15989       return CLI_FAILURE;
15990    }
15991 
15992    return CLI_SUCCESS;
15993 }

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

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

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

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

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

15787 {
15788    int channel;
15789    int gain;
15790    int tx;
15791    struct dahdi_hwgain hwgain;
15792    struct dahdi_pvt *tmp = NULL;
15793 
15794    switch (cmd) {
15795    case CLI_INIT:
15796       e->command = "dahdi set hwgain {rx|tx}";
15797       e->usage =
15798          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15799          "   Sets the hardware gain on a given channel.  Changes take effect\n"
15800          "   immediately whether the channel is in use or not.\n"
15801          "\n"
15802          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15803          "   <chan num> is the channel number relative to the device\n"
15804          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
15805          "\n"
15806          "   Please note:\n"
15807          "   * This is currently the only way to set hwgain by the channel driver.\n"
15808          "   * hwgain is only supportable by hardware with analog ports because\n"
15809          "     hwgain works on the analog side of an analog-digital conversion.\n";
15810       return NULL;
15811    case CLI_GENERATE:
15812       return NULL;
15813    }
15814 
15815    if (a->argc != 6)
15816       return CLI_SHOWUSAGE;
15817 
15818    if (!strcasecmp("rx", a->argv[3]))
15819       tx = 0; /* rx */
15820    else if (!strcasecmp("tx", a->argv[3]))
15821       tx = 1; /* tx */
15822    else
15823       return CLI_SHOWUSAGE;
15824 
15825    channel = atoi(a->argv[4]);
15826    gain = atof(a->argv[5])*10.0;
15827 
15828    ast_mutex_lock(&iflock);
15829 
15830    for (tmp = iflist; tmp; tmp = tmp->next) {
15831 
15832       if (tmp->channel != channel)
15833          continue;
15834 
15835       if (tmp->subs[SUB_REAL].dfd == -1)
15836          break;
15837 
15838       hwgain.newgain = gain;
15839       hwgain.tx = tx;
15840       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15841          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15842          ast_mutex_unlock(&iflock);
15843          return CLI_FAILURE;
15844       }
15845       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15846          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15847       break;
15848    }
15849 
15850    ast_mutex_unlock(&iflock);
15851 
15852    if (tmp)
15853       return CLI_SUCCESS;
15854 
15855    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15856    return CLI_FAILURE;
15857 
15858 }

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

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

15861 {
15862    int channel;
15863    float gain;
15864    int tx;
15865    int res;
15866    struct dahdi_pvt *tmp = NULL;
15867 
15868    switch (cmd) {
15869    case CLI_INIT:
15870       e->command = "dahdi set swgain {rx|tx}";
15871       e->usage =
15872          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15873          "   Sets the software gain on a given channel and overrides the\n"
15874          "   value provided at module loadtime.  Changes take effect\n"
15875          "   immediately whether the channel is in use or not.\n"
15876          "\n"
15877          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15878          "   <chan num> is the channel number relative to the device\n"
15879          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15880       return NULL;
15881    case CLI_GENERATE:
15882       return NULL;
15883    }
15884 
15885    if (a->argc != 6)
15886       return CLI_SHOWUSAGE;
15887 
15888    if (!strcasecmp("rx", a->argv[3]))
15889       tx = 0; /* rx */
15890    else if (!strcasecmp("tx", a->argv[3]))
15891       tx = 1; /* tx */
15892    else
15893       return CLI_SHOWUSAGE;
15894 
15895    channel = atoi(a->argv[4]);
15896    gain = atof(a->argv[5]);
15897 
15898    ast_mutex_lock(&iflock);
15899    for (tmp = iflist; tmp; tmp = tmp->next) {
15900 
15901       if (tmp->channel != channel)
15902          continue;
15903 
15904       if (tmp->subs[SUB_REAL].dfd == -1)
15905          break;
15906 
15907       if (tx)
15908          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15909       else
15910          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15911 
15912       if (res) {
15913          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15914          ast_mutex_unlock(&iflock);
15915          return CLI_FAILURE;
15916       }
15917 
15918       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15919          tx ? "tx" : "rx", gain, channel);
15920 
15921       if (tx) {
15922          tmp->txgain = gain;
15923       } else {
15924          tmp->rxgain = gain;
15925       }
15926       break;
15927    }
15928    ast_mutex_unlock(&iflock);
15929 
15930    if (tmp)
15931       return CLI_SUCCESS;
15932 
15933    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15934    return CLI_FAILURE;
15935 
15936 }

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

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

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

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

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

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

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

15362 {
15363 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15364 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15365    ast_group_t targetnum = 0;
15366    int filtertype = 0;
15367    struct dahdi_pvt *tmp = NULL;
15368    char tmps[20] = "";
15369    char statestr[20] = "";
15370    char blockstr[20] = "";
15371 
15372    switch (cmd) {
15373    case CLI_INIT:
15374       e->command = "dahdi show channels [group|context]";
15375       e->usage =
15376          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15377          "  Shows a list of available channels with optional filtering\n"
15378          "  <group> must be a number between 0 and 63\n";
15379       return NULL;
15380    case CLI_GENERATE:
15381       return NULL;
15382    }
15383 
15384    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15385 
15386    if (!((a->argc == 3) || (a->argc == 5)))
15387       return CLI_SHOWUSAGE;
15388 
15389    if (a->argc == 5) {
15390       if (!strcasecmp(a->argv[3], "group")) {
15391          targetnum = atoi(a->argv[4]);
15392          if (63 < targetnum) {
15393             return CLI_SHOWUSAGE;
15394          }
15395          targetnum = ((ast_group_t) 1) << targetnum;
15396          filtertype = 1;
15397       } else if (!strcasecmp(a->argv[3], "context")) {
15398          filtertype = 2;
15399       }
15400    }
15401 
15402    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15403    ast_mutex_lock(&iflock);
15404    for (tmp = iflist; tmp; tmp = tmp->next) {
15405       if (filtertype) {
15406          switch(filtertype) {
15407          case 1: /* dahdi show channels group <group> */
15408             if (!(tmp->group & targetnum)) {
15409                continue;
15410             }
15411             break;
15412          case 2: /* dahdi show channels context <context> */
15413             if (strcasecmp(tmp->context, a->argv[4])) {
15414                continue;
15415             }
15416             break;
15417          default:
15418             break;
15419          }
15420       }
15421       if (tmp->channel > 0) {
15422          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15423       } else
15424          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15425 
15426       if (tmp->locallyblocked)
15427          blockstr[0] = 'L';
15428       else
15429          blockstr[0] = ' ';
15430 
15431       if (tmp->remotelyblocked)
15432          blockstr[1] = 'R';
15433       else
15434          blockstr[1] = ' ';
15435 
15436       blockstr[2] = '\0';
15437 
15438       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15439 
15440       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15441    }
15442    ast_mutex_unlock(&iflock);
15443    return CLI_SUCCESS;
15444 #undef FORMAT
15445 #undef FORMAT2
15446 }

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

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

15671 {
15672    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15673    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15674    int span;
15675    int res;
15676    char alarmstr[50];
15677 
15678    int ctl;
15679    struct dahdi_spaninfo s;
15680 
15681    switch (cmd) {
15682    case CLI_INIT:
15683       e->command = "dahdi show status";
15684       e->usage =
15685          "Usage: dahdi show status\n"
15686          "       Shows a list of DAHDI cards with status\n";
15687       return NULL;
15688    case CLI_GENERATE:
15689       return NULL;
15690    }
15691    ctl = open("/dev/dahdi/ctl", O_RDWR);
15692    if (ctl < 0) {
15693       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15694       return CLI_FAILURE;
15695    }
15696    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15697 
15698    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15699       s.spanno = span;
15700       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15701       if (res) {
15702          continue;
15703       }
15704       alarmstr[0] = '\0';
15705       if (s.alarms > 0) {
15706          if (s.alarms & DAHDI_ALARM_BLUE)
15707             strcat(alarmstr, "BLU/");
15708          if (s.alarms & DAHDI_ALARM_YELLOW)
15709             strcat(alarmstr, "YEL/");
15710          if (s.alarms & DAHDI_ALARM_RED)
15711             strcat(alarmstr, "RED/");
15712          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15713             strcat(alarmstr, "LB/");
15714          if (s.alarms & DAHDI_ALARM_RECOVER)
15715             strcat(alarmstr, "REC/");
15716          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15717             strcat(alarmstr, "NOP/");
15718          if (!strlen(alarmstr))
15719             strcat(alarmstr, "UUU/");
15720          if (strlen(alarmstr)) {
15721             /* Strip trailing / */
15722             alarmstr[strlen(alarmstr) - 1] = '\0';
15723          }
15724       } else {
15725          if (s.numchans)
15726             strcpy(alarmstr, "OK");
15727          else
15728             strcpy(alarmstr, "UNCONFIGURED");
15729       }
15730 
15731       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15732          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15733          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15734          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15735          "CAS",
15736          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15737          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15738          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15739          "Unk",
15740          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15741             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15742             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15743          lbostr[s.lbo]
15744          );
15745    }
15746    close(ctl);
15747 
15748    return CLI_SUCCESS;
15749 #undef FORMAT
15750 #undef FORMAT2
15751 }

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

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

15754 {
15755    int pseudo_fd = -1;
15756    struct dahdi_versioninfo vi;
15757 
15758    switch (cmd) {
15759    case CLI_INIT:
15760       e->command = "dahdi show version";
15761       e->usage =
15762          "Usage: dahdi show version\n"
15763          "       Shows the DAHDI version in use\n";
15764       return NULL;
15765    case CLI_GENERATE:
15766       return NULL;
15767    }
15768    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15769       ast_cli(a->fd, "Failed to open control file to get version.\n");
15770       return CLI_SUCCESS;
15771    }
15772 
15773    strcpy(vi.version, "Unknown");
15774    strcpy(vi.echo_canceller, "Unknown");
15775 
15776    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15777       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15778    else
15779       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15780 
15781    close(pseudo_fd);
15782 
15783    return CLI_SUCCESS;
15784 }

static char* dahdi_sig2str ( int  sig  )  [static]

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

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

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

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

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

static void dahdi_softhangup_all ( void   )  [static]

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

15188 {
15189    struct dahdi_pvt *p;
15190 retry:
15191    ast_mutex_lock(&iflock);
15192    for (p = iflist; p; p = p->next) {
15193       ast_mutex_lock(&p->lock);
15194       if (p->owner && !p->restartpending) {
15195          if (ast_channel_trylock(p->owner)) {
15196             if (option_debug > 2)
15197                ast_verbose("Avoiding deadlock\n");
15198             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15199             ast_mutex_unlock(&p->lock);
15200             ast_mutex_unlock(&iflock);
15201             goto retry;
15202          }
15203          if (option_debug > 2)
15204             ast_verbose("Softhanging up on %s\n", p->owner->name);
15205          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15206          p->restartpending = 1;
15207          num_restart_pending++;
15208          ast_channel_unlock(p->owner);
15209       }
15210       ast_mutex_unlock(&p->lock);
15211    }
15212    ast_mutex_unlock(&iflock);
15213 }

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

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

18550 {
18551    int ctl, res, span;
18552    struct ast_data *data_span, *data_alarms;
18553    struct dahdi_spaninfo s;
18554 
18555    ctl = open("/dev/dahdi/ctl", O_RDWR);
18556    if (ctl < 0) {
18557       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18558       return -1;
18559    }
18560    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18561       s.spanno = span;
18562       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18563       if (res) {
18564          continue;
18565       }
18566 
18567       data_span = ast_data_add_node(data_root, "span");
18568       if (!data_span) {
18569          continue;
18570       }
18571       ast_data_add_str(data_span, "description", s.desc);
18572 
18573       /* insert the alarms status */
18574       data_alarms = ast_data_add_node(data_span, "alarms");
18575       if (!data_alarms) {
18576          continue;
18577       }
18578 
18579       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18580       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18581       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18582       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18583       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18584       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18585 
18586       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18587       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18588       ast_data_add_int(data_span, "crc4", s.crc4count);
18589       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18590                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18591                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18592                      "CAS");
18593       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18594                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18595                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18596                      "Unknown");
18597       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18598                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18599                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18600       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18601 
18602       /* if this span doesn't match remove it. */
18603       if (!ast_data_search_match(search, data_span)) {
18604          ast_data_remove_node(data_root, data_span);
18605       }
18606    }
18607    close(ctl);
18608 
18609    return 0;
18610 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

Definition at line 18651 of file chan_dahdi.c.

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

18653 {
18654    int pseudo_fd = -1;
18655    struct dahdi_versioninfo vi = {
18656       .version = "Unknown",
18657       .echo_canceller = "Unknown"
18658    };
18659 
18660    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18661       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18662       return -1;
18663    }
18664 
18665    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18666       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18667    }
18668 
18669    close(pseudo_fd);
18670 
18671    ast_data_add_str(data_root, "value", vi.version);
18672    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18673 
18674    return 0;
18675 }

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

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

Referenced by analog_ss_thread(), and my_wink().

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

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

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

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

static enum analog_event dahdievent_to_analogevent ( int  event  )  [static]

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

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

static enum analog_sigtype dahdisig_to_analogsig ( int  sig  )  [static]

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

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

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

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

18214 {
18215    struct ast_cc_config_params *cc_params;
18216 
18217    cc_params = dest->chan.cc_params;
18218    *dest = *src;
18219    dest->chan.cc_params = cc_params;
18220    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18221 }

static void destroy_all_channels ( void   )  [static]

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

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

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

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

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

static void destroy_dahdi_pvt ( struct dahdi_pvt pvt  )  [static]

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

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

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

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

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

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

Definition at line 12305 of file chan_dahdi.c.

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

Referenced by build_channels().

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

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 4484 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

04485 {
04486    if (isdigit(digit))
04487       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04488    else if (digit >= 'A' && digit <= 'D')
04489       return DAHDI_TONE_DTMF_A + (digit - 'A');
04490    else if (digit >= 'a' && digit <= 'd')
04491       return DAHDI_TONE_DTMF_A + (digit - 'a');
04492    else if (digit == '*')
04493       return DAHDI_TONE_DTMF_s;
04494    else if (digit == '#')
04495       return DAHDI_TONE_DTMF_p;
04496    else
04497       return -1;
04498 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

Definition at line 4987 of file chan_dahdi.c.

Referenced by fill_rxgain(), and fill_txgain().

04988 {
04989    float neg;
04990    float shallow, steep;
04991    float max = SHRT_MAX;
04992    
04993    neg = (sample < 0 ? -1 : 1);
04994    steep = drc*sample;
04995    shallow = neg*(max-max/drc)+(float)sample/drc;
04996    if (abs(steep) < abs(shallow)) {
04997       sample = steep;
04998    }
04999    else {
05000       sample = shallow;
05001    }
05002 
05003    return sample;
05004 }

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

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

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

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

06672 {
06673    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06674 
06675    if (p->channel == CHAN_PSEUDO)
06676       return;
06677 
06678    p->ignoredtmf = 0;
06679 
06680    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06681 
06682    if (!p->hardwaredtmf && p->dsp) {
06683       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06684       ast_dsp_set_features(p->dsp, p->dsp_features);
06685    }
06686 }

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

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

04640 {
04641    static char buf[256];
04642    if ((event < (ARRAY_LEN(events))) && (event > -1))
04643       return events[event];
04644    sprintf(buf, "Event %d", event); /* safe */
04645    return buf;
04646 }

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

Definition at line 5057 of file chan_dahdi.c.

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

Referenced by set_actual_rxgain().

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

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

Definition at line 5007 of file chan_dahdi.c.

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

Referenced by set_actual_txgain().

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

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

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

16028 {
16029    struct dahdi_pvt *p;
16030 
16031    ast_mutex_lock(&iflock);
16032    for (p = iflist; p; p = p->next) {
16033       if (p->channel == channel) {
16034          break;
16035       }
16036    }
16037    ast_mutex_unlock(&iflock);
16038    return p;
16039 }

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

Definition at line 16050 of file chan_dahdi.c.

References find_channel().

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

16051 {
16052    int chan_num;
16053 
16054    if (sscanf(channel, "%30d", &chan_num) != 1) {
16055       /* Not numeric string. */
16056       return NULL;
16057    }
16058 
16059    return find_channel(chan_num);
16060 }

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

Definition at line 5747 of file chan_dahdi.c.

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

Referenced by destroy_dahdi_pvt().

05748 {
05749    if (cur->next && cur->next->span == cur->span) {
05750       return cur->next;
05751    } else if (cur->prev && cur->prev->span == cur->span) {
05752       return cur->prev;
05753    }
05754 
05755    return NULL;
05756 }

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

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

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

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

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

static void handle_clear_alarms ( struct dahdi_pvt p  )  [static]

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

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

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

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

15634 {
15635    int i, j;
15636    switch (cmd) {
15637    case CLI_INIT:
15638       e->command = "dahdi show cadences";
15639       e->usage =
15640          "Usage: dahdi show cadences\n"
15641          "       Shows all cadences currently defined\n";
15642       return NULL;
15643    case CLI_GENERATE:
15644       return NULL;
15645    }
15646    for (i = 0; i < num_cadence; i++) {
15647       char output[1024];
15648       char tmp[16], tmp2[64];
15649       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15650       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15651 
15652       for (j = 0; j < 16; j++) {
15653          if (cadences[i].ringcadence[j] == 0)
15654             break;
15655          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15656          if (cidrings[i] * 2 - 1 == j)
15657             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15658          else
15659             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15660          if (j != 0)
15661             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15662          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15663       }
15664       ast_cli(a->fd,"%s\n",output);
15665    }
15666    return CLI_SUCCESS;
15667 }

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

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

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

static int has_voicemail ( struct dahdi_pvt p  )  [static]

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

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

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

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

Referenced by dahdi_cc_callback(), and dahdi_request().

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

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

Definition at line 4752 of file chan_dahdi.c.

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

Referenced by conf_del().

04753 {
04754    /* If they're listening to our channel, they're ours */
04755    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04756       return 1;
04757    /* If they're a talker on our (allocated) conference, they're ours */
04758    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04759       return 1;
04760    return 0;
04761 }

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

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

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

static int load_module ( void   )  [static]

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

18699 {
18700    int res;
18701 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18702    int y;
18703 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18704 
18705 #ifdef HAVE_PRI
18706    memset(pris, 0, sizeof(pris));
18707    for (y = 0; y < NUM_SPANS; y++) {
18708       sig_pri_init_pri(&pris[y].pri);
18709    }
18710    pri_set_error(dahdi_pri_error);
18711    pri_set_message(dahdi_pri_message);
18712    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18713 #ifdef HAVE_PRI_PROG_W_CAUSE
18714    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18715 #endif
18716 #if defined(HAVE_PRI_CCSS)
18717    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18718       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18719       __unload_module();
18720       return AST_MODULE_LOAD_FAILURE;
18721    }
18722 #endif   /* defined(HAVE_PRI_CCSS) */
18723    if (sig_pri_load(
18724 #if defined(HAVE_PRI_CCSS)
18725       dahdi_pri_cc_type
18726 #else
18727       NULL
18728 #endif   /* defined(HAVE_PRI_CCSS) */
18729       )) {
18730       __unload_module();
18731       return AST_MODULE_LOAD_FAILURE;
18732    }
18733 #endif
18734 #if defined(HAVE_SS7)
18735    memset(linksets, 0, sizeof(linksets));
18736    for (y = 0; y < NUM_SPANS; y++) {
18737       sig_ss7_init_linkset(&linksets[y].ss7);
18738    }
18739    ss7_set_error(dahdi_ss7_error);
18740    ss7_set_message(dahdi_ss7_message);
18741 #endif   /* defined(HAVE_SS7) */
18742    res = setup_dahdi(0);
18743    /* Make sure we can register our DAHDI channel type */
18744    if (res)
18745       return AST_MODULE_LOAD_DECLINE;
18746    if (ast_channel_register(&dahdi_tech)) {
18747       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18748       __unload_module();
18749       return AST_MODULE_LOAD_FAILURE;
18750    }
18751 #ifdef HAVE_PRI
18752    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18753 #endif
18754 #if defined(HAVE_SS7)
18755    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18756 #endif   /* defined(HAVE_SS7) */
18757 #ifdef HAVE_OPENR2
18758    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18759    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18760 #endif
18761 
18762    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18763    /* register all the data providers */
18764    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18765    memset(round_robin, 0, sizeof(round_robin));
18766    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18767    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18768    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18769    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18770    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18771    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18772    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18773 
18774    ast_cond_init(&ss_thread_complete, NULL);
18775 
18776    return res;
18777 }

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

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

static void monitor_pfds_clean ( void *  arg  )  [static]

Definition at line 11715 of file chan_dahdi.c.

References ast_free.

Referenced by do_monitor().

11715                                           {
11716    struct pollfd **pfds = arg;
11717    ast_free(*pfds);
11718 }

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

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

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

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

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

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

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

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

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

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

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

static void my_all_subchannels_hungup ( void *  pvt  )  [static]

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

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

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

Definition at line 2750 of file chan_dahdi.c.

References alloc_sub(), and analogsub_to_dahdisub().

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

static void my_answer_polarityswitch ( void *  pvt  )  [static]

Definition at line 2988 of file chan_dahdi.c.

References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().

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

static int my_callwait ( void *  pvt  )  [static]

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

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

static void my_cancel_cidspill ( void *  pvt  )  [static]

Definition at line 2389 of file chan_dahdi.c.

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

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

static int my_check_confirmanswer ( void *  pvt  )  [static]

Definition at line 2372 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

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

static int my_check_for_conference ( void *  pvt  )  [static]

Definition at line 2549 of file chan_dahdi.c.

References check_for_conference().

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

static int my_check_waitingfordt ( void *  pvt  )  [static]

Definition at line 2355 of file chan_dahdi.c.

References dahdi_pvt::waitingfordt.

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

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

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

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

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

Definition at line 2489 of file chan_dahdi.c.

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

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

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

Definition at line 2479 of file chan_dahdi.c.

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

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

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

Definition at line 2398 of file chan_dahdi.c.

References dahdi_confmute().

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

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

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

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

static void my_deadlock_avoidance_private ( void *  pvt  )  [static]

Definition at line 2149 of file chan_dahdi.c.

References DEADLOCK_AVOIDANCE, and dahdi_pvt::lock.

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

static void my_decrease_ss_count ( void   )  [static]

Definition at line 2431 of file chan_dahdi.c.

References ast_cond_signal, ast_mutex_lock, and ast_mutex_unlock.

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

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

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

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

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

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

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

static int my_dsp_reset_and_flush_digits ( void *  pvt  )  [static]

Definition at line 1999 of file chan_dahdi.c.

References ast_dsp_digitreset(), and dahdi_pvt::dsp.

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

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

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

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

static int my_flash ( void *  pvt  )  [static]

Definition at line 2947 of file chan_dahdi.c.

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

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

static void my_get_and_handle_alarms ( void *  pvt  )  [static]

Definition at line 2235 of file chan_dahdi.c.

References get_alarms(), and handle_alarms().

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

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

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

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

static int my_get_event ( void *  pvt  )  [static]

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

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

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

Definition at line 2417 of file chan_dahdi.c.

References dahdi_pvt::dialstring.

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

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

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

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

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

Definition at line 2258 of file chan_dahdi.c.

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

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

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

Definition at line 9849 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by analog_ss_thread().

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

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

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

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

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

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

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

static void my_hangup_polarityswitch ( void *  pvt  )  [static]

Definition at line 2999 of file chan_dahdi.c.

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

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

static int my_has_voicemail ( void *  pvt  )  [static]

Definition at line 2759 of file chan_dahdi.c.

References has_voicemail().

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

static int my_have_progressdetect ( void *  pvt  )  [static]

Definition at line 3691 of file chan_dahdi.c.

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

03692 {
03693    struct dahdi_pvt *p = pvt;
03694 
03695    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03696       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03697       return 1;
03698    } else {
03699       /* Don't have progress detection. */
03700       return 0;
03701    }
03702 }

static void my_increase_ss_count ( void   )  [static]

Definition at line 2424 of file chan_dahdi.c.

References ast_mutex_lock, and ast_mutex_unlock.

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

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

Definition at line 3064 of file chan_dahdi.c.

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

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

static int my_is_off_hook ( void *  pvt  )  [static]

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

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

static void my_lock_private ( void *  pvt  )  [static]

Definition at line 2137 of file chan_dahdi.c.

References ast_mutex_lock, and dahdi_pvt::lock.

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

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

References analogsub_to_dahdisub(), and dahdi_new().

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

static int my_off_hook ( void *  pvt  )  [static]

Definition at line 2956 of file chan_dahdi.c.

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

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

static int my_on_hook ( void *  pvt  )  [static]

Definition at line 3080 of file chan_dahdi.c.

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

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

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

Definition at line 2766 of file chan_dahdi.c.

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

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

static int my_ring ( void *  pvt  )  [static]

Definition at line 2940 of file chan_dahdi.c.

References dahdi_ring_phone().

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

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

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

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

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

Definition at line 2281 of file chan_dahdi.c.

References dahdi_pvt::inalarm.

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

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

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

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

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

Definition at line 2382 of file chan_dahdi.c.

References dahdi_pvt::callwaiting.

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

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

Definition at line 2366 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

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

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

Definition at line 2288 of file chan_dahdi.c.

References dahdi_pvt::dialing.

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

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

Definition at line 2926 of file chan_dahdi.c.

References dahdi_disable_ec(), and dahdi_enable_ec().

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

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

Definition at line 2225 of file chan_dahdi.c.

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

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

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

Definition at line 2213 of file chan_dahdi.c.

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

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

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

Definition at line 2962 of file chan_dahdi.c.

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

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

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

Definition at line 2410 of file chan_dahdi.c.

References dahdi_pvt::owner.

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

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

Definition at line 2295 of file chan_dahdi.c.

References dahdi_pvt::outgoing.

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

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

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

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

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

Definition at line 2404 of file chan_dahdi.c.

References dahdi_pvt::pulsedial.

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

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

Definition at line 2338 of file chan_dahdi.c.

References dahdi_pvt::ringt.

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

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

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

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

static int my_start ( void *  pvt  )  [static]

Definition at line 3014 of file chan_dahdi.c.

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

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

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

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

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

static void my_start_polarityswitch ( void *  pvt  )  [static]

Definition at line 2979 of file chan_dahdi.c.

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

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

static int my_stop_callwait ( void *  pvt  )  [static]

Definition at line 1917 of file chan_dahdi.c.

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

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

static int my_stop_cid_detect ( void *  pvt  )  [static]

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

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

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

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

static int my_train_echocanceller ( void *  pvt  )  [static]

Definition at line 3055 of file chan_dahdi.c.

References dahdi_train_ec().

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

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

Definition at line 2741 of file chan_dahdi.c.

References analogsub_to_dahdisub(), and unalloc_sub().

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

static void my_unlock_private ( void *  pvt  )  [static]

Definition at line 2143 of file chan_dahdi.c.

References ast_mutex_unlock, and dahdi_pvt::lock.

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

static int my_wait_event ( void *  pvt  )  [static]

Definition at line 2873 of file chan_dahdi.c.

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

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

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

Definition at line 2049 of file chan_dahdi.c.

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

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

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

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

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

Definition at line 7058 of file chan_dahdi.c.

References ast_log(), and LOG_WARNING.

Referenced by dahdi_func_write(), and process_dahdi().

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

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

Definition at line 16952 of file chan_dahdi.c.

References string_replace().

Referenced by build_channels().

16953 {
16954    char *p;
16955 
16956    if ((p = strrchr(chanstr, '!')) == NULL) {
16957       *subdir = NULL;
16958       return chanstr;
16959    }
16960    *p++ = '\0';
16961    string_replace(chanstr, '!', '/');
16962    *subdir = chanstr;
16963    return p;
16964 }

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

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

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

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

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

17040 {
17041    char *parse = ast_strdupa(data);
17042    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17043    unsigned int param_count;
17044    unsigned int x;
17045 
17046    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17047       return;
17048 
17049    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17050 
17051    /* first parameter is tap length, process it here */
17052 
17053    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17054 
17055    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17056       confp->chan.echocancel.head.tap_length = x;
17057    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17058       confp->chan.echocancel.head.tap_length = 128;
17059 
17060    /* now process any remaining parameters */
17061 
17062    for (x = 1; x < param_count; x++) {
17063       struct {
17064          char *name;
17065          char *value;
17066       } param;
17067 
17068       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
17069          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
17070          continue;
17071       }
17072 
17073       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17074          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
17075          continue;
17076       }
17077 
17078       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17079 
17080       if (param.value) {
17081          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17082             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
17083             continue;
17084          }
17085       }
17086       confp->chan.echocancel.head.param_count++;
17087    }
17088 }

static int reload ( void   )  [static]

Definition at line 18879 of file chan_dahdi.c.

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

18880 {
18881    int res = 0;
18882 
18883    res = setup_dahdi(1);
18884    if (res) {
18885       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18886       return -1;
18887    }
18888    return 0;
18889 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

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

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

static int restart_monitor ( void   )  [static]

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

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

static int restore_conference ( struct dahdi_pvt p  )  [static]

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

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

static int restore_gains ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

static int save_conference ( struct dahdi_pvt p  )  [static]

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

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

static int send_callerid ( struct dahdi_pvt p  )  [static]

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

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

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

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

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

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

Definition at line 5139 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

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

05140 {
05141    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05142 }

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

Definition at line 5122 of file chan_dahdi.c.

References ast_debug, errno, and fill_rxgain().

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

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

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

Definition at line 5105 of file chan_dahdi.c.

References ast_debug, errno, and fill_txgain().

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

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

static int setup_dahdi ( int  reload  )  [static]

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

18523 {
18524    int res;
18525    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18526    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18527    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18528 
18529    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18530       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18531    } else {
18532       res = -1;
18533    }
18534    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18535    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18536    ast_cc_config_params_destroy(conf.chan.cc_params);
18537 
18538    return res;
18539 }

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

References ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_config_new(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, deep_copy_dahdi_chan_conf(), global_jbconf, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sig_ss7_linkset::master, ast_variable::name, ast_variable::next, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_dahdi(), sig_pri_span::pvts, restart_monitor(), sig_pri_start_pri(), sig_ss7_linkset::ss7, ss7_linkset(), and ast_variable::value.

Referenced by setup_dahdi().

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

static int sigtype_to_signalling ( int  sigtype  )  [static]

Definition at line 12288 of file chan_dahdi.c.

Referenced by mkintf().

12289 {
12290    return sigtype;
12291 }

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

Definition at line 16943 of file chan_dahdi.c.

Referenced by parse_spanchan().

16944 {
16945    for (; *str; str++) {
16946       if (*str == char1) {
16947          *str = char2;
16948       }
16949    }
16950 }

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

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

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

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

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

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

static int unload_module ( void   )  [static]

Definition at line 16927 of file chan_dahdi.c.

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

16928 {
16929 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16930    int y;
16931 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16932 #ifdef HAVE_PRI
16933    for (y = 0; y < NUM_SPANS; y++)
16934       ast_mutex_destroy(&pris[y].pri.lock);
16935 #endif
16936 #if defined(HAVE_SS7)
16937    for (y = 0; y < NUM_SPANS; y++)
16938       ast_mutex_destroy(&linksets[y].ss7.lock);
16939 #endif   /* defined(HAVE_SS7) */
16940    return __unload_module();
16941 }

static int update_conf ( struct dahdi_pvt p  )  [static]

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

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

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

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

03829 {
03830    dahdi_lock_sub_owner(p, a);
03831    if (p->subs[a].owner) {
03832       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03833       ast_channel_unlock(p->subs[a].owner);
03834    }
03835 }


Variable Documentation

int alarm

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

Initial value:

Definition at line 18682 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

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

Initial value:

Definition at line 18677 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 1501 of file chan_dahdi.c.

Initial value:

Definition at line 18687 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 4594 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 4618 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 3775 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 15 Apr 2016 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1