Sat Feb 11 06:34:29 2012

Asterisk developer's documentation


chan_dahdi.c File Reference

DAHDI for Pseudo TDM. More...

#include "asterisk.h"
#include <sys/signal.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <math.h>
#include <ctype.h>
#include <dahdi/user.h>
#include <dahdi/tonezone.h>
#include "sig_analog.h"
#include "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 %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
#define FORMAT2   "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT2   "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\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 void __reg_module (void)
static int __unload_module (void)
static void __unreg_module (void)
static int _dahdi_get_index (struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
static int action_dahdidialoffhook (struct mansession *s, const struct message *m)
static int action_dahdidndoff (struct mansession *s, const struct message *m)
static int action_dahdidndon (struct mansession *s, const struct message *m)
static int action_dahdirestart (struct mansession *s, const struct message *m)
static int action_dahdishowchannels (struct mansession *s, const struct message *m)
static int action_transfer (struct mansession *s, const struct message *m)
static int action_transferhangup (struct mansession *s, const struct message *m)
static char * alarm2str (int alm)
static int alloc_sub (struct dahdi_pvt *p, int x)
static int analog_lib_handles (int signalling, int radio, int oprmode)
static void * analog_ss_thread (void *data)
static int analog_tone_to_dahditone (enum analog_tone tone)
static int analogsub_to_dahdisub (enum analog_sub analogsub)
 AST_DATA_STRUCTURE (dahdi_pvt, DATA_EXPORT_DAHDI_PVT)
static int attempt_transfer (struct dahdi_pvt *p)
static int available (struct dahdi_pvt **pvt, int is_specific_channel)
static int build_channels (struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
static int bump_gains (struct dahdi_pvt *p)
static int calc_energy (const unsigned char *buf, int len, enum ast_format_id 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, const 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 (const char *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, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
static int dahdi_restart (void)
static char * dahdi_restart_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_ring_phone (struct dahdi_pvt *p)
static int dahdi_sendtext (struct ast_channel *c, const char *text)
static char * dahdi_set_dnd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_set_hook (int fd, int hs)
static char * dahdi_set_hwgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_set_swgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_setlinear (int dfd, int linear)
static int dahdi_setoption (struct ast_channel *chan, int option, void *data, int datalen)
static char * dahdi_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_sig2str (int sig)
static int dahdi_sig_pri_lib_handles (int signaling)
static void dahdi_softhangup_all (void)
static int dahdi_status_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static void dahdi_train_ec (struct dahdi_pvt *p)
static void dahdi_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
static int dahdi_version_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static int dahdi_wait_event (int fd)
 Avoid the silly dahdi_waitevent which ignores a bunch of events.
static int dahdi_wink (struct dahdi_pvt *p, int index)
static int dahdi_write (struct ast_channel *ast, struct ast_frame *frame)
static enum analog_event dahdievent_to_analogevent (int event)
static enum analog_sigtype dahdisig_to_analogsig (int sig)
static void deep_copy_dahdi_chan_conf (struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
static void destroy_all_channels (void)
static void destroy_channel (struct dahdi_pvt *cur, int now)
static void destroy_dahdi_pvt (struct dahdi_pvt *pvt)
static struct dahdi_pvtdetermine_starting_point (const char *data, struct dahdi_starting_point *param)
static int device2chan (const char *subdir, int channel, char *path, int pathlen)
static int digit_to_dtmfindex (char digit)
static void disable_dtmf_detect (struct dahdi_pvt *p)
static void * do_monitor (void *data)
static int drc_sample (int sample, float drc)
static struct dahdi_pvtduplicate_pseudo (struct dahdi_pvt *src)
static void enable_dtmf_detect (struct dahdi_pvt *p)
static const char * event2str (int event)
static void fill_rxgain (struct dahdi_gains *g, float gain, float drc, int law)
static void fill_txgain (struct dahdi_gains *g, float gain, float drc, int law)
static struct dahdi_pvtfind_channel (int channel)
static struct dahdi_pvtfind_channel_from_str (const char *channel)
static struct dahdi_pvtfind_next_iface_in_span (struct dahdi_pvt *cur)
static int get_alarms (struct dahdi_pvt *p)
static void handle_alarms (struct dahdi_pvt *p, int alms)
static void handle_clear_alarms (struct dahdi_pvt *p)
static char * handle_dahdi_show_cadences (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct dahdi_pvthandle_init_event (struct dahdi_pvt *i, int event)
static int has_voicemail (struct dahdi_pvt *p)
static int is_group_or_channel_match (struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
static int isourconf (struct dahdi_pvt *p, struct dahdi_subchannel *c)
static int isslavenative (struct dahdi_pvt *p, struct dahdi_pvt **out)
static int load_module (void)
static struct dahdi_pvtmkintf (int channel, const struct dahdi_chan_conf *conf, int reloading)
static void mwi_event_cb (const struct ast_event *event, void *userdata)
static int mwi_send_init (struct dahdi_pvt *pvt)
static int mwi_send_process_buffer (struct dahdi_pvt *pvt, int num_read)
static int mwi_send_process_event (struct dahdi_pvt *pvt, int event)
static void * mwi_thread (void *data)
static void my_all_subchannels_hungup (void *pvt)
static int my_allocate_sub (void *pvt, enum analog_sub analogsub)
static void my_answer_polarityswitch (void *pvt)
static int my_callwait (void *pvt)
static void my_cancel_cidspill (void *pvt)
static int my_check_confirmanswer (void *pvt)
static int my_check_for_conference (void *pvt)
static int my_check_waitingfordt (void *pvt)
static int my_complete_conference_update (void *pvt, int needconference)
static int my_conf_add (void *pvt, enum analog_sub sub)
static int my_conf_del (void *pvt, enum analog_sub sub)
static int my_confmute (void *pvt, int mute)
static int my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
static void my_deadlock_avoidance_private (void *pvt)
static void my_decrease_ss_count (void)
static int my_dial_digits (void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
static int my_distinctive_ring (struct ast_channel *chan, void *pvt, int idx, int *ringdata)
static int my_dsp_reset_and_flush_digits (void *pvt)
static int my_dsp_set_digitmode (void *pvt, enum analog_dsp_digitmode mode)
static int my_flash (void *pvt)
static void my_get_and_handle_alarms (void *pvt)
static int my_get_callerid (void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
static int my_get_event (void *pvt)
static const char * my_get_orig_dialstring (void *pvt)
static void * my_get_sigpvt_bridged_channel (struct ast_channel *chan)
static int my_get_sub_fd (void *pvt, enum analog_sub sub)
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
static void my_handle_dtmf (void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
static void my_handle_notify_message (struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
static void my_hangup_polarityswitch (void *pvt)
static int my_has_voicemail (void *pvt)
static int my_have_progressdetect (void *pvt)
static void my_increase_ss_count (void)
static int my_is_dialing (void *pvt, enum analog_sub sub)
static int my_is_off_hook (void *pvt)
static void my_lock_private (void *pvt)
static struct ast_channelmy_new_analog_ast_channel (void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
static int my_off_hook (void *pvt)
static int my_on_hook (void *pvt)
static int my_play_tone (void *pvt, enum analog_sub sub, enum analog_tone tone)
static int my_ring (void *pvt)
static int my_send_callerid (void *pvt, int cwcid, struct ast_party_caller *caller)
static void my_set_alarm (void *pvt, int in_alarm)
static void my_set_cadence (void *pvt, int *cidrings, 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_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 void parse_busy_pattern (struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
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

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = tdesc , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_smdi", }
struct {
   int   alarm
   char *   name
alarms []
static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}
static struct ast_module_infoast_module_info = &__mod_info
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
static int cidrings [NUM_CADENCE_MAX]
 cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.
static const char config [] = "chan_dahdi.conf"
static 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 ast_mutex_t iflock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
 Protect the interface list (of dahdi_pvt's).
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 ast_mutex_t monlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static int mwilevel = 512
static char mwimonitornotify [PATH_MAX] = ""
static int 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 ast_mutex_t restart_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base.
static struct dahdi_pvtround_robin [32]
static ast_cond_t ss_thread_complete
static int ss_thread_count = 0
static ast_mutex_t ss_thread_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
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 395 of file chan_dahdi.c.

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

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 394 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 393 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_PROGRESS   1

Definition at line 392 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 530 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 529 of file chan_dahdi.c.

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

100 ms

Definition at line 531 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 425 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 532 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 677 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 678 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 1254 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 326 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

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

8,000 ms

Definition at line 534 of file chan_dahdi.c.

#define END_SILENCE_LEN   400

Referenced by dahdi_sendtext().

#define FORMAT   "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"

#define FORMAT   "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"

#define FORMAT2   "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"

#define FORMAT2   "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"

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

Definition at line 1551 of file chan_dahdi.c.

Referenced by my_complete_conference_update(), and update_conf().

#define HANGUP   1

Definition at line 15881 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 422 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 526 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

#define MAX_SLAVES   4

#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

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

Referenced by analog_ss_thread(), and dahdi_new().

#define NUM_CADENCE_MAX   25

Definition at line 397 of file chan_dahdi.c.

Referenced by process_dahdi().

#define NUM_SPANS   32

Definition at line 387 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 17101 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 17103 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 524 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 447 of file chan_dahdi.c.

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

#define REPORT_SPAN_ALARMS   2

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

Referenced by dahdi_sig2str(), and process_dahdi().

#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)

Definition at line 374 of file chan_dahdi.c.

Referenced by dahdi_sig2str(), 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 372 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 289 of file chan_dahdi.c.

Referenced by analog_ss_thread().

#define SUB_CALLWAIT   1

#define SUB_REAL   0

Active call

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

00701                   {
00702    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00703    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00704 #if defined(HAVE_PRI)
00705    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00706 #endif   /* defined(HAVE_PRI) */
00707 };

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

00685              {
00686    MWI_SEND_NULL = 0,
00687    MWI_SEND_SA,
00688    MWI_SEND_SA_WAIT,
00689    MWI_SEND_PAUSE,
00690    MWI_SEND_SPILL,
00691    MWI_SEND_CLEANUP,
00692    MWI_SEND_DONE,
00693 } mwisend_states;


Function Documentation

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

Definition at line 8792 of file chan_dahdi.c.

References ast_channel::_state, ast_bridged_channel(), ast_channel_name(), AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_set_hangupsource(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_tvnow(), ast_verb, dahdi_pvt::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, LOG_WARNING, ast_frame::mallocd, 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().

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

static void __reg_module ( void   )  [static]

Definition at line 19032 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

Definition at line 16761 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_format_cap_destroy(), ast_manager_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), ast_channel_tech::capabilities, destroy_all_channels(), iflock, sig_ss7_linkset::master, monlock, 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().

16762 {
16763    struct dahdi_pvt *p;
16764 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16765    int i, j;
16766 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16767 
16768 #ifdef HAVE_PRI
16769    for (i = 0; i < NUM_SPANS; i++) {
16770       if (pris[i].pri.master != AST_PTHREADT_NULL)
16771          pthread_cancel(pris[i].pri.master);
16772    }
16773    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16774    ast_unregister_application(dahdi_send_keypad_facility_app);
16775 #ifdef HAVE_PRI_PROG_W_CAUSE
16776    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16777 #endif
16778 #endif
16779 #if defined(HAVE_SS7)
16780    for (i = 0; i < NUM_SPANS; i++) {
16781       if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16782          pthread_cancel(linksets[i].ss7.master);
16783       }
16784    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16785 #endif   /* defined(HAVE_SS7) */
16786 #if defined(HAVE_OPENR2)
16787    dahdi_r2_destroy_links();
16788    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16789    ast_unregister_application(dahdi_accept_r2_call_app);
16790 #endif
16791 
16792    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16793    ast_manager_unregister("DAHDIDialOffhook");
16794    ast_manager_unregister("DAHDIHangup");
16795    ast_manager_unregister("DAHDITransfer");
16796    ast_manager_unregister("DAHDIDNDoff");
16797    ast_manager_unregister("DAHDIDNDon");
16798    ast_manager_unregister("DAHDIShowChannels");
16799    ast_manager_unregister("DAHDIRestart");
16800 #if defined(HAVE_PRI)
16801    ast_manager_unregister("PRIShowSpans");
16802 #endif   /* defined(HAVE_PRI) */
16803    ast_data_unregister(NULL);
16804    ast_channel_unregister(&dahdi_tech);
16805 
16806    /* Hangup all interfaces if they have an owner */
16807    ast_mutex_lock(&iflock);
16808    for (p = iflist; p; p = p->next) {
16809       if (p->owner)
16810          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16811    }
16812    ast_mutex_unlock(&iflock);
16813 
16814    ast_mutex_lock(&monlock);
16815    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16816       pthread_cancel(monitor_thread);
16817       pthread_kill(monitor_thread, SIGURG);
16818       pthread_join(monitor_thread, NULL);
16819    }
16820    monitor_thread = AST_PTHREADT_STOP;
16821    ast_mutex_unlock(&monlock);
16822 
16823    destroy_all_channels();
16824 
16825 #if defined(HAVE_PRI)
16826    for (i = 0; i < NUM_SPANS; i++) {
16827       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16828          pthread_join(pris[i].pri.master, NULL);
16829       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16830          dahdi_close_pri_fd(&(pris[i]), j);
16831       }
16832       sig_pri_stop_pri(&pris[i].pri);
16833    }
16834 #if defined(HAVE_PRI_CCSS)
16835    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16836    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16837 #endif   /* defined(HAVE_PRI_CCSS) */
16838    sig_pri_unload();
16839 #endif
16840 
16841 #if defined(HAVE_SS7)
16842    for (i = 0; i < NUM_SPANS; i++) {
16843       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16844          pthread_join(linksets[i].ss7.master, NULL);
16845       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16846          dahdi_close_ss7_fd(&(linksets[i]), j);
16847       }
16848    }
16849 #endif   /* defined(HAVE_SS7) */
16850    ast_cond_destroy(&ss_thread_complete);
16851 
16852    dahdi_tech.capabilities = ast_format_cap_destroy(dahdi_tech.capabilities);
16853    return 0;
16854 }

static void __unreg_module ( void   )  [static]

Definition at line 19032 of file chan_dahdi.c.

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

Definition at line 3738 of file chan_dahdi.c.

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

03739 {
03740    int res;
03741    if (p->subs[SUB_REAL].owner == ast)
03742       res = 0;
03743    else if (p->subs[SUB_CALLWAIT].owner == ast)
03744       res = 1;
03745    else if (p->subs[SUB_THREEWAY].owner == ast)
03746       res = 2;
03747    else {
03748       res = -1;
03749       if (!nullok)
03750          ast_log(LOG_WARNING,
03751             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03752             ast ? ast_channel_name(ast) : "", p->channel, fname, line);
03753    }
03754    return res;
03755 }

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

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

16019 {
16020    struct dahdi_pvt *p;
16021    const char *channel = astman_get_header(m, "DAHDIChannel");
16022    const char *number = astman_get_header(m, "Number");
16023    int i;
16024 
16025    if (ast_strlen_zero(channel)) {
16026       astman_send_error(s, m, "No channel specified");
16027       return 0;
16028    }
16029    if (ast_strlen_zero(number)) {
16030       astman_send_error(s, m, "No number specified");
16031       return 0;
16032    }
16033    p = find_channel_from_str(channel);
16034    if (!p) {
16035       astman_send_error(s, m, "No such channel");
16036       return 0;
16037    }
16038    if (!p->owner) {
16039       astman_send_error(s, m, "Channel does not have it's owner");
16040       return 0;
16041    }
16042    for (i = 0; i < strlen(number); i++) {
16043       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16044       dahdi_queue_frame(p, &f);
16045    }
16046    astman_send_ack(s, m, "DAHDIDialOffhook");
16047    return 0;
16048 }

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

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

15954 {
15955    struct dahdi_pvt *p;
15956    const char *channel = astman_get_header(m, "DAHDIChannel");
15957 
15958    if (ast_strlen_zero(channel)) {
15959       astman_send_error(s, m, "No channel specified");
15960       return 0;
15961    }
15962    p = find_channel_from_str(channel);
15963    if (!p) {
15964       astman_send_error(s, m, "No such channel");
15965       return 0;
15966    }
15967    dahdi_dnd(p, 0);
15968    astman_send_ack(s, m, "DND Disabled");
15969    return 0;
15970 }

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

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

15935 {
15936    struct dahdi_pvt *p;
15937    const char *channel = astman_get_header(m, "DAHDIChannel");
15938 
15939    if (ast_strlen_zero(channel)) {
15940       astman_send_error(s, m, "No channel specified");
15941       return 0;
15942    }
15943    p = find_channel_from_str(channel);
15944    if (!p) {
15945       astman_send_error(s, m, "No such channel");
15946       return 0;
15947    }
15948    dahdi_dnd(p, 1);
15949    astman_send_ack(s, m, "DND Enabled");
15950    return 0;
15951 }

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

Definition at line 15232 of file chan_dahdi.c.

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

Referenced by load_module().

15233 {
15234    if (dahdi_restart() != 0) {
15235       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15236       return 1;
15237    }
15238    astman_send_ack(s, m, "DAHDIRestart: Success");
15239    return 0;
15240 }

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

Definition at line 16050 of file chan_dahdi.c.

References alarm2str(), ast_channel_accountcode(), ast_channel_name(), ast_channel_uniqueid(), 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(), dahdi_pvt::description, get_alarms(), iflock, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::sig, and sig2str.

Referenced by load_module().

16051 {
16052    struct dahdi_pvt *tmp = NULL;
16053    const char *id = astman_get_header(m, "ActionID");
16054    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16055    char idText[256] = "";
16056    int channels = 0;
16057    int dahdichanquery;
16058 
16059    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16060       /* Not numeric string. */
16061       dahdichanquery = -1;
16062    }
16063 
16064    astman_send_ack(s, m, "DAHDI channel status will follow");
16065    if (!ast_strlen_zero(id))
16066       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16067 
16068    ast_mutex_lock(&iflock);
16069 
16070    for (tmp = iflist; tmp; tmp = tmp->next) {
16071       if (tmp->channel > 0) {
16072          int alm;
16073 
16074          /* If a specific channel is queried for, only deliver status for that channel */
16075          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16076             continue;
16077 
16078          alm = get_alarms(tmp);
16079          channels++;
16080          if (tmp->owner) {
16081             /* Add data if we have a current call */
16082             astman_append(s,
16083                "Event: DAHDIShowChannels\r\n"
16084                "DAHDIChannel: %d\r\n"
16085                "Channel: %s\r\n"
16086                "Uniqueid: %s\r\n"
16087                "AccountCode: %s\r\n"
16088                "Signalling: %s\r\n"
16089                "SignallingCode: %d\r\n"
16090                "Context: %s\r\n"
16091                "DND: %s\r\n"
16092                "Alarm: %s\r\n"
16093                "Description: %s\r\n"
16094                "%s"
16095                "\r\n",
16096                tmp->channel,
16097                ast_channel_name(tmp->owner),
16098                ast_channel_uniqueid(tmp->owner),
16099                ast_channel_accountcode(tmp->owner),
16100                sig2str(tmp->sig),
16101                tmp->sig,
16102                tmp->context,
16103                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16104                alarm2str(alm),
16105                tmp->description, idText);
16106          } else {
16107             astman_append(s,
16108                "Event: DAHDIShowChannels\r\n"
16109                "DAHDIChannel: %d\r\n"
16110                "Signalling: %s\r\n"
16111                "SignallingCode: %d\r\n"
16112                "Context: %s\r\n"
16113                "DND: %s\r\n"
16114                "Alarm: %s\r\n"
16115                "Description: %s\r\n"
16116                "%s"
16117                "\r\n",
16118                tmp->channel, sig2str(tmp->sig), tmp->sig,
16119                tmp->context,
16120                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16121                alarm2str(alm),
16122                tmp->description, idText);
16123          }
16124       }
16125    }
16126 
16127    ast_mutex_unlock(&iflock);
16128 
16129    astman_append(s,
16130       "Event: DAHDIShowChannelsComplete\r\n"
16131       "%s"
16132       "Items: %d\r\n"
16133       "\r\n",
16134       idText,
16135       channels);
16136    return 0;
16137 }

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

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

15973 {
15974    struct dahdi_pvt *p;
15975    const char *channel = astman_get_header(m, "DAHDIChannel");
15976 
15977    if (ast_strlen_zero(channel)) {
15978       astman_send_error(s, m, "No channel specified");
15979       return 0;
15980    }
15981    p = find_channel_from_str(channel);
15982    if (!p) {
15983       astman_send_error(s, m, "No such channel");
15984       return 0;
15985    }
15986    if (!analog_lib_handles(p->sig, 0, 0)) {
15987       astman_send_error(s, m, "Channel signaling is not analog");
15988       return 0;
15989    }
15990    dahdi_fake_event(p,TRANSFER);
15991    astman_send_ack(s, m, "DAHDITransfer");
15992    return 0;
15993 }

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

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

15996 {
15997    struct dahdi_pvt *p;
15998    const char *channel = astman_get_header(m, "DAHDIChannel");
15999 
16000    if (ast_strlen_zero(channel)) {
16001       astman_send_error(s, m, "No channel specified");
16002       return 0;
16003    }
16004    p = find_channel_from_str(channel);
16005    if (!p) {
16006       astman_send_error(s, m, "No such channel");
16007       return 0;
16008    }
16009    if (!analog_lib_handles(p->sig, 0, 0)) {
16010       astman_send_error(s, m, "Channel signaling is not analog");
16011       return 0;
16012    }
16013    dahdi_fake_event(p,HANGUP);
16014    astman_send_ack(s, m, "DAHDIHangup");
16015    return 0;
16016 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 4580 of file chan_dahdi.c.

References alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

04581 {
04582    int x;
04583    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04584       if (alarms[x].alarm & alm)
04585          return alarms[x].name;
04586    }
04587    return alm ? "Unknown Alarm" : "No Alarm";
04588 }

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

Definition at line 4384 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(), build_device(), dahdi_handle_event(), HandleCallOutgoing(), my_allocate_sub(), and rcv_mac_addr().

04385 {
04386    struct dahdi_bufferinfo bi;
04387    int res;
04388    if (p->subs[x].dfd >= 0) {
04389       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04390       return -1;
04391    }
04392 
04393    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04394    if (p->subs[x].dfd <= -1) {
04395       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04396       return -1;
04397    }
04398 
04399    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04400    if (!res) {
04401       bi.txbufpolicy = p->buf_policy;
04402       bi.rxbufpolicy = p->buf_policy;
04403       bi.numbufs = p->buf_no;
04404       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04405       if (res < 0) {
04406          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04407       }
04408    } else
04409       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04410 
04411    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04412       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04413       dahdi_close_sub(p, x);
04414       p->subs[x].dfd = -1;
04415       return -1;
04416    }
04417    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04418    return 0;
04419 }

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

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

04666 {
04667    switch (signalling) {
04668    case SIG_FXOLS:
04669    case SIG_FXOGS:
04670    case SIG_FXOKS:
04671    case SIG_FXSLS:
04672    case SIG_FXSGS:
04673    case SIG_FXSKS:
04674    case SIG_EMWINK:
04675    case SIG_EM:
04676    case SIG_EM_E1:
04677    case SIG_FEATD:
04678    case SIG_FEATDMF:
04679    case SIG_E911:
04680    case SIG_FGC_CAMA:
04681    case SIG_FGC_CAMAMF:
04682    case SIG_FEATB:
04683    case SIG_SFWINK:
04684    case SIG_SF:
04685    case SIG_SF_FEATD:
04686    case SIG_SF_FEATDMF:
04687    case SIG_FEATDMF_TA:
04688    case SIG_SF_FEATB:
04689       break;
04690    default:
04691       /* The rest of the function should cover the remainder of signalling types */
04692       return 0;
04693    }
04694 
04695    if (radio)
04696       return 0;
04697 
04698    if (oprmode)
04699       return 0;
04700 
04701    return 1;
04702 }

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

Definition at line 9917 of file chan_dahdi.c.

References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), ast_channel_language(), ast_channel_name(), 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_format_set(), AST_FRAME_DTMF, ast_frfree, ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log(), ast_masq_park_call_exten(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_parking_ext_valid(), ast_party_name_free(), ast_party_name_init(), ast_party_number_free(), ast_party_number_init(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_queue_control(), ast_read(), ast_safe_sleep(), ast_set_callerid(), ast_set_flag, ast_setstate(), ast_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_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_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, ss_thread_lock, ast_party_number::str, strsep(), 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().

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

static int analog_tone_to_dahditone ( enum analog_tone  tone  )  [static]

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

01635 {
01636    switch (tone) {
01637    case ANALOG_TONE_RINGTONE:
01638       return DAHDI_TONE_RINGTONE;
01639    case ANALOG_TONE_STUTTER:
01640       return DAHDI_TONE_STUTTER;
01641    case ANALOG_TONE_CONGESTION:
01642       return DAHDI_TONE_CONGESTION;
01643    case ANALOG_TONE_DIALTONE:
01644       return DAHDI_TONE_DIALTONE;
01645    case ANALOG_TONE_DIALRECALL:
01646       return DAHDI_TONE_DIALRECALL;
01647    case ANALOG_TONE_INFO:
01648       return DAHDI_TONE_INFO;
01649    default:
01650       return -1;
01651    }
01652 }

static int analogsub_to_dahdisub ( enum analog_sub  analogsub  )  [static]

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

01655 {
01656    int index;
01657 
01658    switch (analogsub) {
01659    case ANALOG_SUB_REAL:
01660       index = SUB_REAL;
01661       break;
01662    case ANALOG_SUB_CALLWAIT:
01663       index = SUB_CALLWAIT;
01664       break;
01665    case ANALOG_SUB_THREEWAY:
01666       index = SUB_THREEWAY;
01667       break;
01668    default:
01669       ast_log(LOG_ERROR, "Unidentified sub!\n");
01670       index = SUB_REAL;
01671    }
01672 
01673    return index;
01674 }

AST_DATA_STRUCTURE ( dahdi_pvt  ,
DATA_EXPORT_DAHDI_PVT   
)

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

Definition at line 7677 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, ast_bridged_channel(), ast_channel_masquerade(), ast_channel_name(), 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 close_call(), dahdi_handle_event(), handle_request(), and local_attended_transfer().

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

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

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

13223 {
13224    struct dahdi_pvt *p = *pvt;
13225 
13226    if (p->inalarm)
13227       return 0;
13228 
13229    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13230       return analog_available(p->sig_pvt);
13231 
13232    switch (p->sig) {
13233 #if defined(HAVE_PRI)
13234    case SIG_PRI_LIB_HANDLE_CASES:
13235       {
13236          struct sig_pri_chan *pvt_chan;
13237          int res;
13238 
13239          pvt_chan = p->sig_pvt;
13240          res = sig_pri_available(&pvt_chan, is_specific_channel);
13241          *pvt = pvt_chan->chan_pvt;
13242          return res;
13243       }
13244 #endif   /* defined(HAVE_PRI) */
13245 #if defined(HAVE_SS7)
13246    case SIG_SS7:
13247       return sig_ss7_available(p->sig_pvt);
13248 #endif   /* defined(HAVE_SS7) */
13249    default:
13250       break;
13251    }
13252 
13253    if (p->locallyblocked || p->remotelyblocked) {
13254       return 0;
13255    }
13256 
13257    /* If no owner definitely available */
13258    if (!p->owner) {
13259 #ifdef HAVE_OPENR2
13260       /* Trust MFC/R2 */
13261       if (p->mfcr2) {
13262          if (p->mfcr2call) {
13263             return 0;
13264          } else {
13265             return 1;
13266          }
13267       }
13268 #endif
13269       return 1;
13270    }
13271 
13272    return 0;
13273 }

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

Definition at line 16895 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, sig2str, and strsep().

Referenced by process_dahdi().

16896 {
16897    char *c, *chan;
16898    char *subdir;
16899    int x, start, finish;
16900    struct dahdi_pvt *tmp;
16901 
16902    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16903       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16904       return -1;
16905    }
16906 
16907    c = ast_strdupa(value);
16908    c = parse_spanchan(c, &subdir);
16909 
16910    while ((chan = strsep(&c, ","))) {
16911       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16912          /* Range */
16913       } else if (sscanf(chan, "%30d", &start)) {
16914          /* Just one */
16915          finish = start;
16916       } else if (!strcasecmp(chan, "pseudo")) {
16917          finish = start = CHAN_PSEUDO;
16918          if (found_pseudo)
16919             *found_pseudo = 1;
16920       } else {
16921          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16922          return -1;
16923       }
16924       if (finish < start) {
16925          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16926          x = finish;
16927          finish = start;
16928          start = x;
16929       }
16930 
16931       for (x = start; x <= finish; x++) {
16932          char fn[PATH_MAX];
16933          int real_channel = x;
16934 
16935          if (!ast_strlen_zero(subdir)) {
16936             real_channel = device2chan(subdir, x, fn, sizeof(fn));
16937             if (real_channel < 0) {
16938                if (conf->ignore_failed_channels) {
16939                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16940                         subdir, x, real_channel);
16941                   continue;
16942                } else {
16943                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16944                         subdir, x, real_channel);
16945                   return -1;
16946                }
16947             }
16948          }
16949          tmp = mkintf(real_channel, conf, reload);
16950 
16951          if (tmp) {
16952             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16953          } else {
16954             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16955                   (reload == 1) ? "reconfigure" : "register", value);
16956             return -1;
16957          }
16958       }
16959    }
16960 
16961    return 0;
16962 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

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

05123 {
05124    int res;
05125 
05126    /* Bump receive gain by value stored in cid_rxgain */
05127    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05128    if (res) {
05129       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05130       return -1;
05131    }
05132 
05133    return 0;
05134 }

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

Definition at line 11052 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by do_monitor(), and mwi_thread().

11053 {
11054    int x;
11055    int sum = 0;
11056 
11057    if (!len)
11058       return 0;
11059 
11060    for (x = 0; x < len; x++)
11061       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11062 
11063    return sum / len;
11064 }

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

Definition at line 9890 of file chan_dahdi.c.

References ast_pickup_ext(), and pickup_ext.

Referenced by analog_ss_thread().

09891 {
09892    int extlen = strlen(exten);
09893    const char *pickup_ext;
09894    if (!extlen) {
09895       return 1;
09896    }
09897    pickup_ext = ast_pickup_ext();
09898    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09899       return 1;
09900    }
09901    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09902    if (exten[0] == '*' && extlen < 3) {
09903       if (extlen == 1) {
09904          return 1;
09905       }
09906       /* "*0" should be processed before it gets here */
09907       switch (exten[1]) {
09908       case '6':
09909       case '7':
09910       case '8':
09911          return 1;
09912       }
09913    }
09914    return 0;
09915 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

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

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

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

Definition at line 9555 of file chan_dahdi.c.

References ast_channel_name(), 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().

09557 {
09558    struct ast_str *chan_name;
09559    int x, y;
09560 
09561    /* Create the new channel name tail. */
09562    if (!(chan_name = ast_str_create(32))) {
09563       return NULL;
09564    }
09565    if (i->channel == CHAN_PSEUDO) {
09566       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09567 #if defined(HAVE_PRI)
09568    } else if (i->pri) {
09569       ast_mutex_lock(&i->pri->lock);
09570       y = ++i->pri->new_chan_seq;
09571       if (is_outgoing) {
09572          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09573          address[0] = '\0';
09574       } else if (ast_strlen_zero(i->cid_subaddr)) {
09575          /* Put in caller-id number only since there is no subaddress. */
09576          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09577       } else {
09578          /* Put in caller-id number and subaddress. */
09579          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09580             i->cid_subaddr, y);
09581       }
09582       ast_mutex_unlock(&i->pri->lock);
09583 #endif   /* defined(HAVE_PRI) */
09584    } else {
09585       y = 1;
09586       do {
09587          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09588          for (x = 0; x < 3; ++x) {
09589             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09590                ast_channel_name(i->subs[x].owner) + 6)) {
09591                break;
09592             }
09593          }
09594          ++y;
09595       } while (x < 3);
09596    }
09597    return chan_name;
09598 }

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

Definition at line 2156 of file chan_dahdi.c.

References ast_channel_name(), ast_channel_uniqueid(), ast_manager_event, CHAN_PSEUDO, dahdi_pvt::channel, EVENT_FLAG_CALL, and dahdi_pvt::span.

Referenced by dahdi_new().

02157 {
02158    char ch_name[20];
02159 
02160    if (p->channel < CHAN_PSEUDO) {
02161       /* No B channel */
02162       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02163    } else if (p->channel == CHAN_PSEUDO) {
02164       /* Pseudo channel */
02165       strcpy(ch_name, "pseudo");
02166    } else {
02167       /* Real channel */
02168       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02169    }
02170    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02171       "Channel: %s\r\n"
02172       "Uniqueid: %s\r\n"
02173       "DAHDISpan: %d\r\n"
02174       "DAHDIChannel: %s\r\n",
02175       ast_channel_name(chan),
02176       ast_channel_uniqueid(chan),
02177       p->span,
02178       ch_name);
02179 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

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

Definition at line 6591 of file chan_dahdi.c.

References analog_answer(), analog_lib_handles(), ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_UP, dahdi_pvt::channel, dahdi_get_index, dahdi_pvt::lock, 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.

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

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 7238 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_name(), ast_channel_trylock, ast_channel_unlock, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VOICE, ast_frfree, ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_read(), AST_STATE_RINGING, ast_verb, ast_waitfor_n(), ast_write(), sig_pri_chan::call, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index, dahdi_link(), dahdi_sig_pri_lib_handles(), dahdi_unlink(), dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), 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().

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

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

Definition at line 5359 of file chan_dahdi.c.

References ast_channel::_state, analog_call(), analog_lib_handles(), args, AST_APP_ARG, ast_channel_name(), ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_NONSTANDARD_APP_ARGS, ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_UP, ast_strdupa, 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, ext, dahdi_pvt::exten, 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(), sig_pri_extract_called_num_subaddr(), 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.

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

static int dahdi_callwait ( struct ast_channel ast  )  [static]

Definition at line 5325 of file chan_dahdi.c.

References ast_format_set(), 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().

05326 {
05327    struct dahdi_pvt *p = ast->tech_pvt;
05328    struct ast_format tmpfmt;
05329    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05330    if (p->cidspill) {
05331       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05332       ast_free(p->cidspill);
05333    }
05334 
05335    /*
05336     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05337     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05338     */
05339    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05340       return -1;
05341    save_conference(p);
05342    /* Silence */
05343    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05344    if (!p->callwaitrings && p->callwaitingcallerid) {
05345       ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05346       p->callwaitcas = 1;
05347       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05348    } else {
05349       ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05350       p->callwaitcas = 0;
05351       p->cidlen = 2400 + READ_SIZE * 4;
05352    }
05353    p->cidpos = 0;
05354    send_callerid(p);
05355 
05356    return 0;
05357 }

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 13887 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, iflock, is_group_or_channel_match(), dahdi_pvt::next, dahdi_pvt::prev, dahdi_pvt::sig, dahdi_pvt::span, and dahdi_starting_point::span.

13888 {
13889    struct dahdi_pvt *p;
13890    struct dahdi_pvt *exitpvt;
13891    struct dahdi_starting_point start;
13892    int groupmatched = 0;
13893    int channelmatched = 0;
13894 
13895    ast_mutex_lock(&iflock);
13896    p = determine_starting_point(dest, &start);
13897    if (!p) {
13898       ast_mutex_unlock(&iflock);
13899       return -1;
13900    }
13901    exitpvt = p;
13902    for (;;) {
13903       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13904          /* We found a potential match. call the callback */
13905          struct ast_str *device_name;
13906          char *dash;
13907          const char *monitor_type;
13908          char dialstring[AST_CHANNEL_NAME];
13909          char full_device_name[AST_CHANNEL_NAME];
13910 
13911          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13912          case AST_CC_MONITOR_NEVER:
13913             break;
13914          case AST_CC_MONITOR_NATIVE:
13915          case AST_CC_MONITOR_ALWAYS:
13916          case AST_CC_MONITOR_GENERIC:
13917 #if defined(HAVE_PRI)
13918             if (dahdi_sig_pri_lib_handles(p->sig)) {
13919                /*
13920                 * ISDN is in a trunk busy condition so we need to monitor
13921                 * the span congestion device state.
13922                 */
13923                snprintf(full_device_name, sizeof(full_device_name),
13924                   "DAHDI/I%d/congestion", p->pri->span);
13925             } else
13926 #endif   /* defined(HAVE_PRI) */
13927             {
13928 #if defined(HAVE_PRI)
13929                device_name = create_channel_name(p, 1, "");
13930 #else
13931                device_name = create_channel_name(p);
13932 #endif   /* defined(HAVE_PRI) */
13933                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13934                   device_name ? ast_str_buffer(device_name) : "");
13935                ast_free(device_name);
13936                /*
13937                 * The portion after the '-' in the channel name is either a random
13938                 * number, a sequence number, or a subchannel number. None are
13939                 * necessary so strip them off.
13940                 */
13941                dash = strrchr(full_device_name, '-');
13942                if (dash) {
13943                   *dash = '\0';
13944                }
13945             }
13946             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13947 
13948             /*
13949              * Analog can only do generic monitoring.
13950              * ISDN is in a trunk busy condition and any "device" is going
13951              * to be busy until a B channel becomes available.  The generic
13952              * monitor can do this task.
13953              */
13954             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13955             callback(inbound,
13956 #if defined(HAVE_PRI)
13957                p->pri ? p->pri->cc_params : p->cc_params,
13958 #else
13959                p->cc_params,
13960 #endif   /* defined(HAVE_PRI) */
13961                monitor_type, full_device_name, dialstring, NULL);
13962             break;
13963          }
13964       }
13965       p = start.backwards ? p->prev : p->next;
13966       if (!p) {
13967          p = start.backwards ? ifend : iflist;
13968       }
13969       if (p == exitpvt) {
13970          break;
13971       }
13972    }
13973    ast_mutex_unlock(&iflock);
13974    return 0;
13975 }

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

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

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

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

18719 {
18720    struct dahdi_pvt *tmp;
18721    struct ast_data *data_channel;
18722 
18723    ast_mutex_lock(&iflock);
18724    for (tmp = iflist; tmp; tmp = tmp->next) {
18725       data_channel = ast_data_add_node(data_root, "channel");
18726       if (!data_channel) {
18727          continue;
18728       }
18729 
18730       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18731 
18732       /* if this channel doesn't match remove it. */
18733       if (!ast_data_search_match(search, data_channel)) {
18734          ast_data_remove_node(data_root, data_channel);
18735       }
18736    }
18737    ast_mutex_unlock(&iflock);
18738 
18739    return 0;
18740 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 4350 of file chan_dahdi.c.

Referenced by dahdi_close_sub().

04351 {
04352    if (fd > 0)
04353       close(fd);
04354 }

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

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

04357 {
04358    dahdi_close(chan_pvt->subs[sub_num].dfd);
04359    chan_pvt->subs[sub_num].dfd = -1;
04360 }

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

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

05167 {
05168    int x, res;
05169 
05170    x = muted;
05171 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05172    switch (p->sig) {
05173 #if defined(HAVE_PRI)
05174    case SIG_PRI_LIB_HANDLE_CASES:
05175       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05176          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05177          break;
05178       }
05179       /* Fall through */
05180 #endif   /* defined(HAVE_PRI) */
05181 #if defined(HAVE_SS7)
05182    case SIG_SS7:
05183 #endif   /* defined(HAVE_SS7) */
05184       {
05185          int y = 1;
05186 
05187          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05188          if (res)
05189             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05190                p->channel, strerror(errno));
05191       }
05192       break;
05193    default:
05194       break;
05195    }
05196 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05197    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05198    if (res < 0)
05199       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05200    return res;
05201 }

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

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

15048 {
15049    int channel;
15050    int ret;
15051    switch (cmd) {
15052    case CLI_INIT:
15053       e->command = "dahdi destroy channel";
15054       e->usage =
15055          "Usage: dahdi destroy channel <chan num>\n"
15056          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15057       return NULL;
15058    case CLI_GENERATE:
15059       return NULL;
15060    }
15061    if (a->argc != 4)
15062       return CLI_SHOWUSAGE;
15063 
15064    channel = atoi(a->argv[3]);
15065    ret = dahdi_destroy_channel_bynum(channel);
15066    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15067 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

Definition at line 11408 of file chan_dahdi.c.

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

Referenced by dahdi_destroy_channel(), and do_monitor().

11409 {
11410    struct dahdi_pvt *cur;
11411 
11412    ast_mutex_lock(&iflock);
11413    for (cur = iflist; cur; cur = cur->next) {
11414       if (cur->channel == channel) {
11415          int x = DAHDI_FLASH;
11416 
11417          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11418          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11419 
11420          destroy_channel(cur, 1);
11421          ast_mutex_unlock(&iflock);
11422          ast_module_unref(ast_module_info->self);
11423          return RESULT_SUCCESS;
11424       }
11425    }
11426    ast_mutex_unlock(&iflock);
11427    return RESULT_FAILURE;
11428 }

static int dahdi_devicestate ( const char *  data  )  [static]

Definition at line 13825 of file chan_dahdi.c.

References AST_DEVICE_UNKNOWN.

13826 {
13827 #if defined(HAVE_PRI)
13828    const char *device;
13829    unsigned span;
13830    int res;
13831 
13832    device = data;
13833 
13834    if (*device != 'I') {
13835       /* The request is not for an ISDN span device. */
13836       return AST_DEVICE_UNKNOWN;
13837    }
13838    res = sscanf(device, "I%30u", &span);
13839    if (res != 1 || !span || NUM_SPANS < span) {
13840       /* Bad format for ISDN span device name. */
13841       return AST_DEVICE_UNKNOWN;
13842    }
13843    device = strchr(device, '/');
13844    if (!device) {
13845       /* Bad format for ISDN span device name. */
13846       return AST_DEVICE_UNKNOWN;
13847    }
13848 
13849    /*
13850     * Since there are currently no other span devstate's defined,
13851     * it must be congestion.
13852     */
13853 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13854    ++device;
13855    if (!strcmp(device, "congestion"))
13856 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13857    {
13858       return pris[span - 1].pri.congestion_devstate;
13859    }
13860 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13861    else if (!strcmp(device, "threshold")) {
13862       return pris[span - 1].pri.threshold_devstate;
13863    }
13864    return AST_DEVICE_UNKNOWN;
13865 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13866 #else
13867    return AST_DEVICE_UNKNOWN;
13868 #endif   /* defined(HAVE_PRI) */
13869 }

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

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

04455 {
04456    struct dahdi_pvt *pvt;
04457    int idx;
04458    int dtmf = -1;
04459    int res;
04460 
04461    pvt = chan->tech_pvt;
04462 
04463    ast_mutex_lock(&pvt->lock);
04464 
04465    idx = dahdi_get_index(chan, pvt, 0);
04466 
04467    if ((idx != SUB_REAL) || !pvt->owner)
04468       goto out;
04469 
04470 #ifdef HAVE_PRI
04471    switch (pvt->sig) {
04472    case SIG_PRI_LIB_HANDLE_CASES:
04473       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04474       if (!res)
04475          goto out;
04476       break;
04477    default:
04478       break;
04479    }
04480 #endif
04481    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04482       goto out;
04483 
04484    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04485       struct dahdi_dialoperation zo = {
04486          .op = DAHDI_DIAL_OP_APPEND,
04487       };
04488 
04489       zo.dialstr[0] = 'T';
04490       zo.dialstr[1] = digit;
04491       zo.dialstr[2] = '\0';
04492       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04493          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
04494       else
04495          pvt->dialing = 1;
04496    } else {
04497       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
04498       pvt->dialing = 1;
04499       pvt->begindigit = digit;
04500    }
04501 
04502 out:
04503    ast_mutex_unlock(&pvt->lock);
04504 
04505    return 0;
04506 }

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

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

04509 {
04510    struct dahdi_pvt *pvt;
04511    int res = 0;
04512    int idx;
04513    int x;
04514 
04515    pvt = chan->tech_pvt;
04516 
04517    ast_mutex_lock(&pvt->lock);
04518 
04519    idx = dahdi_get_index(chan, pvt, 0);
04520 
04521    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04522       goto out;
04523 
04524 #ifdef HAVE_PRI
04525    /* This means that the digit was already sent via PRI signalling */
04526    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04527       goto out;
04528    }
04529 #endif
04530 
04531    if (pvt->begindigit) {
04532       x = -1;
04533       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
04534       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04535       pvt->dialing = 0;
04536       pvt->begindigit = 0;
04537    }
04538 
04539 out:
04540    ast_mutex_unlock(&pvt->lock);
04541 
04542    return res;
04543 }

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

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

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

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

09868 {
09869    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09870       return analog_dnd(dahdichan->sig_pvt, flag);
09871    }
09872 
09873    if (flag == -1) {
09874       return dahdichan->dnd;
09875    }
09876 
09877    /* Do not disturb */
09878    dahdichan->dnd = flag;
09879    ast_verb(3, "%s DND on channel %d\n",
09880          flag? "Enabled" : "Disabled",
09881          dahdichan->channel);
09882    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09883          "Channel: DAHDI/%d\r\n"
09884          "Status: %s\r\n", dahdichan->channel,
09885          flag? "enabled" : "disabled");
09886 
09887    return 0;
09888 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

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

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

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

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

08906 {
08907    struct dahdi_pvt *p = ast->tech_pvt;
08908    struct ast_frame *f;
08909    ast_mutex_lock(&p->lock);
08910    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08911       struct analog_pvt *analog_p = p->sig_pvt;
08912       f = analog_exception(analog_p, ast);
08913    } else {
08914       f = __dahdi_exception(ast);
08915    }
08916    ast_mutex_unlock(&p->lock);
08917    return f;
08918 }

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

Definition at line 15883 of file chan_dahdi.c.

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

Referenced by action_transfer(), and action_transferhangup().

15884 {
15885    if (p) {
15886       switch (mode) {
15887       case TRANSFER:
15888          p->fake_event = DAHDI_EVENT_WINKFLASH;
15889          break;
15890       case HANGUP:
15891          p->fake_event = DAHDI_EVENT_ONHOOK;
15892          break;
15893       default:
15894          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, ast_channel_name(p->owner));
15895       }
15896    }
15897    return 0;
15898 }

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

Definition at line 7605 of file chan_dahdi.c.

References ast_channel::_state, analog_fixup(), analog_lib_handles(), ast_channel_name(), 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().

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

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

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

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

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

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

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

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

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

00504 {
00505    int j;
00506    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00507       return -1;
00508    return j;
00509 }

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

Definition at line 7782 of file chan_dahdi.c.

References ast_async_goto(), ast_channel_lock, ast_channel_name(), 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().

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

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

Definition at line 7901 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_name(), ast_channel_trylock, ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup_with_cause(), ast_setstate(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, attempt_transfer(), ast_channel::caller, 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_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().

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

static int dahdi_hangup ( struct ast_channel ast  )  [static]

Definition at line 6169 of file chan_dahdi.c.

References ast_channel::_state, analog_hangup(), analog_lib_handles(), ast_bridged_channel(), ast_channel_name(), 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, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_pvt::law, dahdi_pvt::law_default, dahdi_subchannel::linear, dahdi_pvt::lock, 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.

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

static void dahdi_iflist_extract ( struct dahdi_pvt pvt  )  [static]

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

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

static void dahdi_iflist_insert ( struct dahdi_pvt pvt  )  [static]

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

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

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

Definition at line 9431 of file chan_dahdi.c.

References ast_channel::_state, AST_CAUSE_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_USER_BUSY, ast_channel_name(), 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().

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

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

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

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

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

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

03773 {
03774    for (;;) {
03775       if (!pvt->subs[sub_idx].owner) {
03776          /* No subchannel owner pointer */
03777          break;
03778       }
03779       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03780          /* Got subchannel owner lock */
03781          break;
03782       }
03783       /* We must unlock the private to avoid the possibility of a deadlock */
03784       DEADLOCK_AVOIDANCE(&pvt->lock);
03785    }
03786 }

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

References 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_NAME, ast_channel_set_fd(), ast_copy_string(), ast_debug, AST_DEVICE_UNKNOWN, ast_devstate_changed_literal(), 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_FORMAT_ALAW, ast_format_cap_add(), ast_format_clear(), ast_format_copy(), ast_format_set(), 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_strlen_zero(), dahdi_pvt::busy_cadence, 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_party_redirecting::from, global_jbconf, dahdi_pvt::hardwaredtmf, ast_party_caller::id, 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, 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(), my_new_analog_ast_channel(), and register_translator().

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

static int dahdi_open ( char *  fn  )  [static]

Definition at line 4303 of file chan_dahdi.c.

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

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

04304 {
04305    int fd;
04306    int isnum;
04307    int chan = 0;
04308    int bs;
04309    int x;
04310    isnum = 1;
04311    for (x = 0; x < strlen(fn); x++) {
04312       if (!isdigit(fn[x])) {
04313          isnum = 0;
04314          break;
04315       }
04316    }
04317    if (isnum) {
04318       chan = atoi(fn);
04319       if (chan < 1) {
04320          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04321          return -1;
04322       }
04323       fn = "/dev/dahdi/channel";
04324    }
04325    fd = open(fn, O_RDWR | O_NONBLOCK);
04326    if (fd < 0) {
04327       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04328       return -1;
04329    }
04330    if (chan) {
04331       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04332          x = errno;
04333          close(fd);
04334          errno = x;
04335          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04336          return -1;
04337       }
04338    }
04339    bs = READ_SIZE;
04340    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04341       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04342       x = errno;
04343       close(fd);
04344       errno = x;
04345       return -1;
04346    }
04347    return fd;
04348 }

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

Definition at line 6686 of file chan_dahdi.c.

References ast_channel_name(), 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.

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

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

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

03798 {
03799    for (;;) {
03800       if (p->owner) {
03801          if (ast_channel_trylock(p->owner)) {
03802             DEADLOCK_AVOIDANCE(&p->lock);
03803          } else {
03804             ast_queue_frame(p->owner, f);
03805             ast_channel_unlock(p->owner);
03806             break;
03807          }
03808       } else
03809          break;
03810    }
03811 }

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

Definition at line 8920 of file chan_dahdi.c.

References __dahdi_exception(), ast_channel::_state, analog_exception(), analog_handle_dtmf(), analog_lib_handles(), ast_channel_name(), 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_copy(), AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_log(), ast_mutex_trylock, ast_mutex_unlock, ast_null_frame, ast_queue_frame(), ast_setstate(), AST_STATE_DIALING, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, dahdi_subchannel::buffer, dahdi_pvt::busydetect, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, CHECK_BLOCKING, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidspill, 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_subclass::format, ast_frame::frametype, ast_format::id, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_subchannel::inthreeway, dahdi_subchannel::linear, dahdi_pvt::lock, 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.

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

static struct ast_channel * dahdi_request ( const char *  type,
struct ast_format_cap cap,
const struct ast_channel requestor,
const char *  data,
int *  cause 
) [static, read]

Definition at line 13655 of file chan_dahdi.c.

References analog_lib_handles(), analog_request(), ast_atomic_fetchadd_int(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, ast_channel_linkedid(), 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, iflock, is_group_or_channel_match(), dahdi_pvt::lock, 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.

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

static int dahdi_restart ( void   )  [static]

Definition at line 15098 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, iflock, LOG_WARNING, monlock, dahdi_pvt::next, dahdi_pvt::owner, restart_lock, setup_dahdi(), sig_pri_init_pri(), sig_ss7_init_linkset(), SIG_SS7_NUM_DCHANS, ss_thread_lock, SUB_REAL, and dahdi_pvt::subs.

Referenced by action_dahdirestart(), and dahdi_restart_cmd().

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

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

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

15210 {
15211    switch (cmd) {
15212    case CLI_INIT:
15213       e->command = "dahdi restart";
15214       e->usage =
15215          "Usage: dahdi restart\n"
15216          "  Restarts the DAHDI channels: destroys them all and then\n"
15217          "  re-reads them from chan_dahdi.conf.\n"
15218          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15219          "";
15220       return NULL;
15221    case CLI_GENERATE:
15222       return NULL;
15223    }
15224    if (a->argc != 2)
15225       return CLI_SHOWUSAGE;
15226 
15227    if (dahdi_restart() != 0)
15228       return CLI_FAILURE;
15229    return CLI_SUCCESS;
15230 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

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

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

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

Definition at line 18888 of file chan_dahdi.c.

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

18889 {
18890 #define  END_SILENCE_LEN 400
18891 #define  HEADER_MS 50
18892 #define  TRAILER_MS 5
18893 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18894 #define  ASCII_BYTES_PER_CHAR 80
18895 
18896    unsigned char *buf,*mybuf;
18897    struct dahdi_pvt *p = c->tech_pvt;
18898    struct pollfd fds[1];
18899    int size,res,fd,len,x;
18900    int bytes=0;
18901    int idx;
18902 
18903    /*
18904     * Initial carrier (imaginary)
18905     *
18906     * Note: The following float variables are used by the
18907     * PUT_CLID_MARKMS and PUT_CLID() macros.
18908     */
18909    float cr = 1.0;
18910    float ci = 0.0;
18911    float scont = 0.0;
18912 
18913    if (!text[0]) {
18914       return(0); /* if nothing to send, don't */
18915    }
18916    idx = dahdi_get_index(c, p, 0);
18917    if (idx < 0) {
18918       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18919       return -1;
18920    }
18921    if ((!p->tdd) && (!p->mate)) {
18922 #if defined(HAVE_PRI)
18923 #if defined(HAVE_PRI_DISPLAY_TEXT)
18924       ast_mutex_lock(&p->lock);
18925       if (dahdi_sig_pri_lib_handles(p->sig)) {
18926          sig_pri_sendtext(p->sig_pvt, text);
18927       }
18928       ast_mutex_unlock(&p->lock);
18929 #endif   /* defined(HAVE_PRI_DISPLAY_TEXT) */
18930 #endif   /* defined(HAVE_PRI) */
18931       return(0);  /* if not in TDD mode, just return */
18932    }
18933    if (p->mate)
18934       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18935    else
18936       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18937    if (!buf)
18938       return -1;
18939    mybuf = buf;
18940    if (p->mate) {
18941       struct ast_format tmp;
18942       /* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
18943       struct ast_format *codec = &tmp;
18944       ast_format_set(codec, AST_LAW(p), 0);
18945       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18946          PUT_CLID_MARKMS;
18947       }
18948       /* Put actual message */
18949       for (x = 0; text[x]; x++) {
18950          PUT_CLID(text[x]);
18951       }
18952       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18953          PUT_CLID_MARKMS;
18954       }
18955       len = bytes;
18956       buf = mybuf;
18957    } else {
18958       len = tdd_generate(p->tdd, buf, text);
18959       if (len < 1) {
18960          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18961          ast_free(mybuf);
18962          return -1;
18963       }
18964    }
18965    memset(buf + len, 0x7f, END_SILENCE_LEN);
18966    len += END_SILENCE_LEN;
18967    fd = p->subs[idx].dfd;
18968    while (len) {
18969       if (ast_check_hangup(c)) {
18970          ast_free(mybuf);
18971          return -1;
18972       }
18973       size = len;
18974       if (size > READ_SIZE)
18975          size = READ_SIZE;
18976       fds[0].fd = fd;
18977       fds[0].events = POLLOUT | POLLPRI;
18978       fds[0].revents = 0;
18979       res = poll(fds, 1, -1);
18980       if (!res) {
18981          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18982          continue;
18983       }
18984       /* if got exception */
18985       if (fds[0].revents & POLLPRI) {
18986          ast_free(mybuf);
18987          return -1;
18988       }
18989       if (!(fds[0].revents & POLLOUT)) {
18990          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18991          continue;
18992       }
18993       res = write(fd, buf, size);
18994       if (res != size) {
18995          if (res == -1) {
18996             ast_free(mybuf);
18997             return -1;
18998          }
18999          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
19000          break;
19001       }
19002       len -= size;
19003       buf += size;
19004    }
19005    ast_free(mybuf);
19006    return(0);
19007 }

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

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

15811 {
15812    int channel;
15813    int on;
15814    struct dahdi_pvt *dahdi_chan = NULL;
15815 
15816    switch (cmd) {
15817    case CLI_INIT:
15818       e->command = "dahdi set dnd";
15819       e->usage =
15820          "Usage: dahdi set dnd <chan#> <on|off>\n"
15821          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15822          "  Changes take effect immediately.\n"
15823          "  <chan num> is the channel number\n"
15824          "  <on|off> Enable or disable DND mode?\n"
15825          ;
15826       return NULL;
15827    case CLI_GENERATE:
15828       return NULL;
15829    }
15830 
15831    if (a->argc != 5)
15832       return CLI_SHOWUSAGE;
15833 
15834    if ((channel = atoi(a->argv[3])) <= 0) {
15835       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15836       return CLI_SHOWUSAGE;
15837    }
15838 
15839    if (ast_true(a->argv[4]))
15840       on = 1;
15841    else if (ast_false(a->argv[4]))
15842       on = 0;
15843    else {
15844       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15845       return CLI_SHOWUSAGE;
15846    }
15847 
15848    ast_mutex_lock(&iflock);
15849    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15850       if (dahdi_chan->channel != channel)
15851          continue;
15852 
15853       /* Found the channel. Actually set it */
15854       dahdi_dnd(dahdi_chan, on);
15855       break;
15856    }
15857    ast_mutex_unlock(&iflock);
15858 
15859    if (!dahdi_chan) {
15860       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15861       return CLI_FAILURE;
15862    }
15863 
15864    return CLI_SUCCESS;
15865 }

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

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

05150 {
05151    int x, res;
05152 
05153    x = hs;
05154    res = ioctl(fd, DAHDI_HOOK, &x);
05155 
05156    if (res < 0) {
05157       if (errno == EINPROGRESS)
05158          return 0;
05159       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05160       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05161    }
05162 
05163    return res;
05164 }

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

15671 {
15672    int channel;
15673    int gain;
15674    int tx;
15675    struct dahdi_hwgain hwgain;
15676    struct dahdi_pvt *tmp = NULL;
15677 
15678    switch (cmd) {
15679    case CLI_INIT:
15680       e->command = "dahdi set hwgain";
15681       e->usage =
15682          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15683          "  Sets the hardware gain on a a given channel, overriding the\n"
15684          "   value provided at module loadtime, whether the channel is in\n"
15685          "   use or not.  Changes take effect immediately.\n"
15686          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15687          "   <chan num> is the channel number relative to the device\n"
15688          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15689       return NULL;
15690    case CLI_GENERATE:
15691       return NULL;
15692    }
15693 
15694    if (a->argc != 6)
15695       return CLI_SHOWUSAGE;
15696 
15697    if (!strcasecmp("rx", a->argv[3]))
15698       tx = 0; /* rx */
15699    else if (!strcasecmp("tx", a->argv[3]))
15700       tx = 1; /* tx */
15701    else
15702       return CLI_SHOWUSAGE;
15703 
15704    channel = atoi(a->argv[4]);
15705    gain = atof(a->argv[5])*10.0;
15706 
15707    ast_mutex_lock(&iflock);
15708 
15709    for (tmp = iflist; tmp; tmp = tmp->next) {
15710 
15711       if (tmp->channel != channel)
15712          continue;
15713 
15714       if (tmp->subs[SUB_REAL].dfd == -1)
15715          break;
15716 
15717       hwgain.newgain = gain;
15718       hwgain.tx = tx;
15719       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15720          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15721          ast_mutex_unlock(&iflock);
15722          return CLI_FAILURE;
15723       }
15724       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15725          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15726       break;
15727    }
15728 
15729    ast_mutex_unlock(&iflock);
15730 
15731    if (tmp)
15732       return CLI_SUCCESS;
15733 
15734    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15735    return CLI_FAILURE;
15736 
15737 }

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

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

15740 {
15741    int channel;
15742    float gain;
15743    int tx;
15744    int res;
15745    struct dahdi_pvt *tmp = NULL;
15746 
15747    switch (cmd) {
15748    case CLI_INIT:
15749       e->command = "dahdi set swgain";
15750       e->usage =
15751          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15752          "  Sets the software gain on a a given channel, overriding the\n"
15753          "   value provided at module loadtime, whether the channel is in\n"
15754          "   use or not.  Changes take effect immediately.\n"
15755          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15756          "   <chan num> is the channel number relative to the device\n"
15757          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15758       return NULL;
15759    case CLI_GENERATE:
15760       return NULL;
15761    }
15762 
15763    if (a->argc != 6)
15764       return CLI_SHOWUSAGE;
15765 
15766    if (!strcasecmp("rx", a->argv[3]))
15767       tx = 0; /* rx */
15768    else if (!strcasecmp("tx", a->argv[3]))
15769       tx = 1; /* tx */
15770    else
15771       return CLI_SHOWUSAGE;
15772 
15773    channel = atoi(a->argv[4]);
15774    gain = atof(a->argv[5]);
15775 
15776    ast_mutex_lock(&iflock);
15777    for (tmp = iflist; tmp; tmp = tmp->next) {
15778 
15779       if (tmp->channel != channel)
15780          continue;
15781 
15782       if (tmp->subs[SUB_REAL].dfd == -1)
15783          break;
15784 
15785       if (tx)
15786          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15787       else
15788          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15789 
15790       if (res) {
15791          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15792          ast_mutex_unlock(&iflock);
15793          return CLI_FAILURE;
15794       }
15795 
15796       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15797          tx ? "tx" : "rx", gain, channel);
15798       break;
15799    }
15800    ast_mutex_unlock(&iflock);
15801 
15802    if (tmp)
15803       return CLI_SUCCESS;
15804 
15805    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15806    return CLI_FAILURE;
15807 
15808 }

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

References ast_channel_name(), 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, pp, READ_SIZE, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), dahdi_pvt::sig, dahdi_pvt::sig_pvt, SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::txdrc, dahdi_pvt::txgain, and ast_channel_tech::type.

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

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

Definition at line 15328 of file chan_dahdi.c.

References sig_pri_chan::allocated, ast_cli_args::argc, ast_cli_args::argv, ast_channel_name(), ast_cli(), ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::busy_cadence, 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::description, 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, iflock, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pvt::law_default, ast_dsp_busy_pattern::length, 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, ast_dsp_busy_pattern::pattern, 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, 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.

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

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

Definition at line 15242 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::description, dahdi_pvt::exten, ast_cli_args::fd, FORMAT, FORMAT2, dahdi_pvt::group, iflock, dahdi_pvt::language, dahdi_pvt::locallyblocked, dahdi_pvt::mohinterpret, dahdi_pvt::next, dahdi_pvt::remotelyblocked, and ast_cli_entry::usage.

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

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

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

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

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

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

15638 {
15639    int pseudo_fd = -1;
15640    struct dahdi_versioninfo vi;
15641 
15642    switch (cmd) {
15643    case CLI_INIT:
15644       e->command = "dahdi show version";
15645       e->usage =
15646          "Usage: dahdi show version\n"
15647          "       Shows the DAHDI version in use\n";
15648       return NULL;
15649    case CLI_GENERATE:
15650       return NULL;
15651    }
15652    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15653       ast_cli(a->fd, "Failed to open control file to get version.\n");
15654       return CLI_SUCCESS;
15655    }
15656 
15657    strcpy(vi.version, "Unknown");
15658    strcpy(vi.echo_canceller, "Unknown");
15659 
15660    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15661       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15662    else
15663       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15664 
15665    close(pseudo_fd);
15666 
15667    return CLI_SUCCESS;
15668 }

static char* dahdi_sig2str ( int  sig  )  [static]

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

04600 {
04601    static char buf[256];
04602    switch (sig) {
04603    case SIG_EM:
04604       return "E & M Immediate";
04605    case SIG_EMWINK:
04606       return "E & M Wink";
04607    case SIG_EM_E1:
04608       return "E & M E1";
04609    case SIG_FEATD:
04610       return "Feature Group D (DTMF)";
04611    case SIG_FEATDMF:
04612       return "Feature Group D (MF)";
04613    case SIG_FEATDMF_TA:
04614       return "Feature Groud D (MF) Tandem Access";
04615    case SIG_FEATB:
04616       return "Feature Group B (MF)";
04617    case SIG_E911:
04618       return "E911 (MF)";
04619    case SIG_FGC_CAMA:
04620       return "FGC/CAMA (Dialpulse)";
04621    case SIG_FGC_CAMAMF:
04622       return "FGC/CAMA (MF)";
04623    case SIG_FXSLS:
04624       return "FXS Loopstart";
04625    case SIG_FXSGS:
04626       return "FXS Groundstart";
04627    case SIG_FXSKS:
04628       return "FXS Kewlstart";
04629    case SIG_FXOLS:
04630       return "FXO Loopstart";
04631    case SIG_FXOGS:
04632       return "FXO Groundstart";
04633    case SIG_FXOKS:
04634       return "FXO Kewlstart";
04635    case SIG_PRI:
04636       return "ISDN PRI";
04637    case SIG_BRI:
04638       return "ISDN BRI Point to Point";
04639    case SIG_BRI_PTMP:
04640       return "ISDN BRI Point to MultiPoint";
04641    case SIG_SS7:
04642       return "SS7";
04643    case SIG_MFCR2:
04644       return "MFC/R2";
04645    case SIG_SF:
04646       return "SF (Tone) Immediate";
04647    case SIG_SFWINK:
04648       return "SF (Tone) Wink";
04649    case SIG_SF_FEATD:
04650       return "SF (Tone) with Feature Group D (DTMF)";
04651    case SIG_SF_FEATDMF:
04652       return "SF (Tone) with Feature Group D (MF)";
04653    case SIG_SF_FEATB:
04654       return "SF (Tone) with Feature Group B (MF)";
04655    case 0:
04656       return "Pseudo";
04657    default:
04658       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04659       return buf;
04660    }
04661 }

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

Definition at line 1567 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_sendtext(), dahdi_setoption(), and mkintf().

01568 {
01569    int handles;
01570 
01571    switch (signaling) {
01572    case SIG_PRI_LIB_HANDLE_CASES:
01573       handles = 1;
01574       break;
01575    default:
01576       handles = 0;
01577       break;
01578    }
01579 
01580    return handles;
01581 }

static void dahdi_softhangup_all ( void   )  [static]

Definition at line 15069 of file chan_dahdi.c.

References ast_channel_name(), ast_channel_trylock, ast_channel_unlock, ast_mutex_lock, ast_mutex_unlock, AST_SOFTHANGUP_EXPLICIT, ast_softhangup_nolock(), ast_verbose, iflock, dahdi_pvt::lock, dahdi_pvt::next, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.

Referenced by dahdi_restart().

15070 {
15071    struct dahdi_pvt *p;
15072 retry:
15073    ast_mutex_lock(&iflock);
15074    for (p = iflist; p; p = p->next) {
15075       ast_mutex_lock(&p->lock);
15076       if (p->owner && !p->restartpending) {
15077          if (ast_channel_trylock(p->owner)) {
15078             if (option_debug > 2)
15079                ast_verbose("Avoiding deadlock\n");
15080             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15081             ast_mutex_unlock(&p->lock);
15082             ast_mutex_unlock(&iflock);
15083             goto retry;
15084          }
15085          if (option_debug > 2)
15086             ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15087          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15088          p->restartpending = 1;
15089          num_restart_pending++;
15090          ast_channel_unlock(p->owner);
15091       }
15092       ast_mutex_unlock(&p->lock);
15093    }
15094    ast_mutex_unlock(&iflock);
15095 }

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

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

18648 {
18649    int ctl, res, span;
18650    struct ast_data *data_span, *data_alarms;
18651    struct dahdi_spaninfo s;
18652 
18653    ctl = open("/dev/dahdi/ctl", O_RDWR);
18654    if (ctl < 0) {
18655       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18656       return -1;
18657    }
18658    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18659       s.spanno = span;
18660       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18661       if (res) {
18662          continue;
18663       }
18664 
18665       data_span = ast_data_add_node(data_root, "span");
18666       if (!data_span) {
18667          continue;
18668       }
18669       ast_data_add_str(data_span, "description", s.desc);
18670 
18671       /* insert the alarms status */
18672       data_alarms = ast_data_add_node(data_span, "alarms");
18673       if (!data_alarms) {
18674          continue;
18675       }
18676 
18677       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18678       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18679       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18680       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18681       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18682       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18683 
18684       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18685       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18686       ast_data_add_int(data_span, "crc4", s.crc4count);
18687       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18688                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18689                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18690                      "CAS");
18691       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18692                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18693                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18694                      "Unknown");
18695       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18696                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18697                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18698       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18699 
18700       /* if this span doesn't match remove it. */
18701       if (!ast_data_search_match(search, data_span)) {
18702          ast_data_remove_node(data_root, data_span);
18703       }
18704    }
18705    close(ctl);
18706 
18707    return 0;
18708 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

Definition at line 18749 of file chan_dahdi.c.

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

18751 {
18752    int pseudo_fd = -1;
18753    struct dahdi_versioninfo vi = {
18754       .version = "Unknown",
18755       .echo_canceller = "Unknown"
18756    };
18757 
18758    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18759       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18760       return -1;
18761    }
18762 
18763    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18764       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18765    }
18766 
18767    close(pseudo_fd);
18768 
18769    ast_data_add_str(data_root, "value", vi.version);
18770    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18771 
18772    return 0;
18773 }

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 512 of file chan_dahdi.c.

00513 {
00514    int i, j = 0;
00515    i = DAHDI_IOMUX_SIGEVENT;
00516    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00517       return -1;
00518    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00519       return -1;
00520    return j;
00521 }

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

Definition at line 9840 of file chan_dahdi.c.

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

Referenced by analog_ss_thread(), and my_wink().

09841 {
09842    int j;
09843    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09844    for (;;)
09845    {
09846       /* set bits of interest */
09847       j = DAHDI_IOMUX_SIGEVENT;
09848       /* wait for some happening */
09849       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09850       /* exit loop if we have it */
09851       if (j & DAHDI_IOMUX_SIGEVENT) break;
09852    }
09853    /* get the event info */
09854    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09855    return 0;
09856 }

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

Definition at line 9366 of file chan_dahdi.c.

References ast_channel_name(), 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, dahdi_get_index, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialing, errno, ast_frame_subclass::format, ast_frame::frametype, ast_format::id, 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.

09367 {
09368    struct dahdi_pvt *p = ast->tech_pvt;
09369    int res;
09370    int idx;
09371    idx = dahdi_get_index(ast, p, 0);
09372    if (idx < 0) {
09373       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
09374       return -1;
09375    }
09376 
09377    /* Write a frame of (presumably voice) data */
09378    if (frame->frametype != AST_FRAME_VOICE) {
09379       if (frame->frametype != AST_FRAME_IMAGE)
09380          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09381       return 0;
09382    }
09383    if ((frame->subclass.format.id != AST_FORMAT_SLINEAR) &&
09384       (frame->subclass.format.id != AST_FORMAT_ULAW) &&
09385       (frame->subclass.format.id != AST_FORMAT_ALAW)) {
09386       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
09387       return -1;
09388    }
09389    if (p->dialing) {
09390       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast_channel_name(ast));
09391       return 0;
09392    }
09393    if (!p->owner) {
09394       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast_channel_name(ast));
09395       return 0;
09396    }
09397    if (p->cidspill) {
09398       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09399          ast_channel_name(ast));
09400       return 0;
09401    }
09402    /* Return if it's not valid data */
09403    if (!frame->data.ptr || !frame->datalen)
09404       return 0;
09405 
09406    if (frame->subclass.format.id == AST_FORMAT_SLINEAR) {
09407       if (!p->subs[idx].linear) {
09408          p->subs[idx].linear = 1;
09409          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09410          if (res)
09411             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09412       }
09413       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09414    } else {
09415       /* x-law already */
09416       if (p->subs[idx].linear) {
09417          p->subs[idx].linear = 0;
09418          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09419          if (res)
09420             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09421       }
09422       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09423    }
09424    if (res < 0) {
09425       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09426       return -1;
09427    }
09428    return 0;
09429 }

static enum analog_event dahdievent_to_analogevent ( int  event  )  [static]

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

02755 {
02756    enum analog_event res;
02757 
02758    switch (event) {
02759    case DAHDI_EVENT_ONHOOK:
02760       res = ANALOG_EVENT_ONHOOK;
02761       break;
02762    case DAHDI_EVENT_RINGOFFHOOK:
02763       res = ANALOG_EVENT_RINGOFFHOOK;
02764       break;
02765    case DAHDI_EVENT_WINKFLASH:
02766       res = ANALOG_EVENT_WINKFLASH;
02767       break;
02768    case DAHDI_EVENT_ALARM:
02769       res = ANALOG_EVENT_ALARM;
02770       break;
02771    case DAHDI_EVENT_NOALARM:
02772       res = ANALOG_EVENT_NOALARM;
02773       break;
02774    case DAHDI_EVENT_DIALCOMPLETE:
02775       res = ANALOG_EVENT_DIALCOMPLETE;
02776       break;
02777    case DAHDI_EVENT_RINGERON:
02778       res = ANALOG_EVENT_RINGERON;
02779       break;
02780    case DAHDI_EVENT_RINGEROFF:
02781       res = ANALOG_EVENT_RINGEROFF;
02782       break;
02783    case DAHDI_EVENT_HOOKCOMPLETE:
02784       res = ANALOG_EVENT_HOOKCOMPLETE;
02785       break;
02786    case DAHDI_EVENT_PULSE_START:
02787       res = ANALOG_EVENT_PULSE_START;
02788       break;
02789    case DAHDI_EVENT_POLARITY:
02790       res = ANALOG_EVENT_POLARITY;
02791       break;
02792    case DAHDI_EVENT_RINGBEGIN:
02793       res = ANALOG_EVENT_RINGBEGIN;
02794       break;
02795    case DAHDI_EVENT_EC_DISABLED:
02796       res = ANALOG_EVENT_EC_DISABLED;
02797       break;
02798    case DAHDI_EVENT_REMOVED:
02799       res = ANALOG_EVENT_REMOVED;
02800       break;
02801    case DAHDI_EVENT_NEONMWI_ACTIVE:
02802       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02803       break;
02804    case DAHDI_EVENT_NEONMWI_INACTIVE:
02805       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02806       break;
02807 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02808    case DAHDI_EVENT_TX_CED_DETECTED:
02809       res = ANALOG_EVENT_TX_CED_DETECTED;
02810       break;
02811    case DAHDI_EVENT_RX_CED_DETECTED:
02812       res = ANALOG_EVENT_RX_CED_DETECTED;
02813       break;
02814    case DAHDI_EVENT_EC_NLP_DISABLED:
02815       res = ANALOG_EVENT_EC_NLP_DISABLED;
02816       break;
02817    case DAHDI_EVENT_EC_NLP_ENABLED:
02818       res = ANALOG_EVENT_EC_NLP_ENABLED;
02819       break;
02820 #endif
02821    case DAHDI_EVENT_PULSEDIGIT:
02822       res = ANALOG_EVENT_PULSEDIGIT;
02823       break;
02824    case DAHDI_EVENT_DTMFDOWN:
02825       res = ANALOG_EVENT_DTMFDOWN;
02826       break;
02827    case DAHDI_EVENT_DTMFUP:
02828       res = ANALOG_EVENT_DTMFUP;
02829       break;
02830    default:
02831       switch(event & 0xFFFF0000) {
02832       case DAHDI_EVENT_PULSEDIGIT:
02833       case DAHDI_EVENT_DTMFDOWN:
02834       case DAHDI_EVENT_DTMFUP:
02835          /* The event includes a digit number in the low word.
02836           * Converting it to a 'enum analog_event' would remove
02837           * that information. Thus it is returned as-is.
02838           */
02839          return event;
02840       }
02841 
02842       res = ANALOG_EVENT_ERROR;
02843       break;
02844    }
02845 
02846    return res;
02847 }

static enum analog_sigtype dahdisig_to_analogsig ( int  sig  )  [static]

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

01584 {
01585    switch (sig) {
01586    case SIG_FXOLS:
01587       return ANALOG_SIG_FXOLS;
01588    case SIG_FXOGS:
01589       return ANALOG_SIG_FXOGS;
01590    case SIG_FXOKS:
01591       return ANALOG_SIG_FXOKS;
01592    case SIG_FXSLS:
01593       return ANALOG_SIG_FXSLS;
01594    case SIG_FXSGS:
01595       return ANALOG_SIG_FXSGS;
01596    case SIG_FXSKS:
01597       return ANALOG_SIG_FXSKS;
01598    case SIG_EMWINK:
01599       return ANALOG_SIG_EMWINK;
01600    case SIG_EM:
01601       return ANALOG_SIG_EM;
01602    case SIG_EM_E1:
01603       return ANALOG_SIG_EM_E1;
01604    case SIG_FEATD:
01605       return ANALOG_SIG_FEATD;
01606    case SIG_FEATDMF:
01607       return ANALOG_SIG_FEATDMF;
01608    case SIG_E911:
01609       return SIG_E911;
01610    case SIG_FGC_CAMA:
01611       return ANALOG_SIG_FGC_CAMA;
01612    case SIG_FGC_CAMAMF:
01613       return ANALOG_SIG_FGC_CAMAMF;
01614    case SIG_FEATB:
01615       return ANALOG_SIG_FEATB;
01616    case SIG_SFWINK:
01617       return ANALOG_SIG_SFWINK;
01618    case SIG_SF:
01619       return ANALOG_SIG_SF;
01620    case SIG_SF_FEATD:
01621       return ANALOG_SIG_SF_FEATD;
01622    case SIG_SF_FEATDMF:
01623       return ANALOG_SIG_SF_FEATDMF;
01624    case SIG_FEATDMF_TA:
01625       return ANALOG_SIG_FEATDMF_TA;
01626    case SIG_SF_FEATB:
01627       return ANALOG_SIG_FEATB;
01628    default:
01629       return -1;
01630    }
01631 }

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

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

18312 {
18313    struct ast_cc_config_params *cc_params;
18314 
18315    cc_params = dest->chan.cc_params;
18316    *dest = *src;
18317    dest->chan.cc_params = cc_params;
18318    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18319 }

static void destroy_all_channels ( void   )  [static]

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

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

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

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

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

static void destroy_dahdi_pvt ( struct dahdi_pvt pvt  )  [static]

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

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

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

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

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

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

Definition at line 12259 of file chan_dahdi.c.

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

Referenced by build_channels().

12260 {
12261    struct stat stbuf;
12262    int      num;
12263 
12264    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12265    if (stat(path, &stbuf) < 0) {
12266       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12267       return -errno;
12268    }
12269    if (!S_ISCHR(stbuf.st_mode)) {
12270       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12271       return -EINVAL;
12272    }
12273    num = minor(stbuf.st_rdev);
12274    ast_debug(1, "%s -> %d\n", path, num);
12275    return num;
12276 
12277 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 4438 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

04439 {
04440    if (isdigit(digit))
04441       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04442    else if (digit >= 'A' && digit <= 'D')
04443       return DAHDI_TONE_DTMF_A + (digit - 'A');
04444    else if (digit >= 'a' && digit <= 'd')
04445       return DAHDI_TONE_DTMF_A + (digit - 'a');
04446    else if (digit == '*')
04447       return DAHDI_TONE_DTMF_s;
04448    else if (digit == '#')
04449       return DAHDI_TONE_DTMF_p;
04450    else
04451       return -1;
04452 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

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

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

Definition at line 11676 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_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(), iflock, last, mwi_thread_data::len, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, dahdi_pvt::mailbox, analog_pvt::msgstate, mwi_send_init(), mwi_send_process_buffer(), mwi_send_process_event(), mwi_thread(), dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitoractive, dahdi_pvt::mwisendactive, dahdi_pvt::next, analog_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, analog_subchannel::owner, analog_pvt::owner, mwi_thread_data::pvt, dahdi_pvt::radio, RESULT_SUCCESS, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, dahdi_pvt::sig_pvt, SUB_REAL, analog_pvt::subs, and dahdi_pvt::subs.

Referenced by restart_monitor().

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

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

Definition at line 4977 of file chan_dahdi.c.

Referenced by fill_rxgain(), and fill_txgain().

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

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

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

13431 {
13432    struct dahdi_pvt *p;
13433    struct dahdi_bufferinfo bi;
13434    int res;
13435 
13436    p = ast_malloc(sizeof(*p));
13437    if (!p) {
13438       return NULL;
13439    }
13440    *p = *src;
13441 
13442    /* Must deep copy the cc_params. */
13443    p->cc_params = ast_cc_config_params_init();
13444    if (!p->cc_params) {
13445       ast_free(p);
13446       return NULL;
13447    }
13448    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13449 
13450    p->which_iflist = DAHDI_IFLIST_NONE;
13451    p->next = NULL;
13452    p->prev = NULL;
13453    ast_mutex_init(&p->lock);
13454    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13455    if (p->subs[SUB_REAL].dfd < 0) {
13456       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13457       destroy_dahdi_pvt(p);
13458       return NULL;
13459    }
13460    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13461    if (!res) {
13462       bi.txbufpolicy = src->buf_policy;
13463       bi.rxbufpolicy = src->buf_policy;
13464       bi.numbufs = src->buf_no;
13465       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13466       if (res < 0) {
13467          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13468       }
13469    } else
13470       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13471    p->destroy = 1;
13472    dahdi_iflist_insert(p);
13473    return p;
13474 }

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

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

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

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

04591 {
04592    static char buf[256];
04593    if ((event < (ARRAY_LEN(events))) && (event > -1))
04594       return events[event];
04595    sprintf(buf, "Event %d", event); /* safe */
04596    return buf;
04597 }

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

Definition at line 5041 of file chan_dahdi.c.

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

Referenced by set_actual_rxgain().

05042 {
05043    int j;
05044    int k;
05045    float linear_gain = pow(10.0, gain / 20.0);
05046 
05047    switch (law) {
05048    case DAHDI_LAW_ALAW:
05049       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05050          if (gain || drc) {
05051             k = AST_ALAW(j);
05052             if (drc) {
05053                k = drc_sample(k, drc);
05054             }
05055             k = (float)k*linear_gain;
05056             if (k > 32767) k = 32767;
05057             if (k < -32767) k = -32767;
05058             g->rxgain[j] = AST_LIN2A(k);
05059          } else {
05060             g->rxgain[j] = j;
05061          }
05062       }
05063       break;
05064    case DAHDI_LAW_MULAW:
05065       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05066          if (gain || drc) {
05067             k = AST_MULAW(j);
05068             if (drc) {
05069                k = drc_sample(k, drc);
05070             }
05071             k = (float)k*linear_gain;
05072             if (k > 32767) k = 32767;
05073             if (k < -32767) k = -32767;
05074             g->rxgain[j] = AST_LIN2MU(k);
05075          } else {
05076             g->rxgain[j] = j;
05077          }
05078       }
05079       break;
05080    }
05081 }

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

Definition at line 4997 of file chan_dahdi.c.

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

Referenced by set_actual_txgain().

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

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

Definition at line 15899 of file chan_dahdi.c.

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

Referenced by find_channel_from_str().

15900 {
15901    struct dahdi_pvt *p;
15902 
15903    ast_mutex_lock(&iflock);
15904    for (p = iflist; p; p = p->next) {
15905       if (p->channel == channel) {
15906          break;
15907       }
15908    }
15909    ast_mutex_unlock(&iflock);
15910    return p;
15911 }

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

Definition at line 15922 of file chan_dahdi.c.

References find_channel().

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

15923 {
15924    int chan_num;
15925 
15926    if (sscanf(channel, "%30d", &chan_num) != 1) {
15927       /* Not numeric string. */
15928       return NULL;
15929    }
15930 
15931    return find_channel(chan_num);
15932 }

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

Definition at line 5753 of file chan_dahdi.c.

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

Referenced by destroy_dahdi_pvt().

05754 {
05755    if (cur->next && cur->next->span == cur->span) {
05756       return cur->next;
05757    } else if (cur->prev && cur->prev->span == cur->span) {
05758       return cur->prev;
05759    }
05760 
05761    return NULL;
05762 }

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

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

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

Definition at line 7880 of file chan_dahdi.c.

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

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

07881 {
07882    const char *alarm_str = alarm2str(alms);
07883 
07884    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07885       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07886       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07887                  "Alarm: %s\r\n"
07888                  "Channel: %d\r\n",
07889                  alarm_str, p->channel);
07890    }
07891 
07892    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07893       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07894       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07895                  "Alarm: %s\r\n"
07896                  "Span: %d\r\n",
07897                  alarm_str, p->span);
07898    }
07899 }

static void handle_clear_alarms ( struct dahdi_pvt p  )  [static]

Definition at line 3813 of file chan_dahdi.c.

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

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

03814 {
03815    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03816       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03817       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03818    }
03819    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03820       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03821       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03822    }
03823 }

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

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

15518 {
15519    int i, j;
15520    switch (cmd) {
15521    case CLI_INIT:
15522       e->command = "dahdi show cadences";
15523       e->usage =
15524          "Usage: dahdi show cadences\n"
15525          "       Shows all cadences currently defined\n";
15526       return NULL;
15527    case CLI_GENERATE:
15528       return NULL;
15529    }
15530    for (i = 0; i < num_cadence; i++) {
15531       char output[1024];
15532       char tmp[16], tmp2[64];
15533       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15534       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15535 
15536       for (j = 0; j < 16; j++) {
15537          if (cadences[i].ringcadence[j] == 0)
15538             break;
15539          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15540          if (cidrings[i] * 2 - 1 == j)
15541             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15542          else
15543             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15544          if (j != 0)
15545             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15546          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15547       }
15548       ast_cli(a->fd,"%s\n",output);
15549    }
15550    return CLI_SUCCESS;
15551 }

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

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

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

static int has_voicemail ( struct dahdi_pvt p  )  [static]

Definition at line 5262 of file chan_dahdi.c.

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

05263 {
05264    int new_msgs;
05265    struct ast_event *event;
05266    char *mailbox, *context;
05267 
05268    mailbox = context = ast_strdupa(p->mailbox);
05269    strsep(&context, "@");
05270    if (ast_strlen_zero(context))
05271       context = "default";
05272 
05273    event = ast_event_get_cached(AST_EVENT_MWI,
05274       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05275       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05276       AST_EVENT_IE_END);
05277 
05278    if (event) {
05279       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05280       ast_event_destroy(event);
05281    } else
05282       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05283 
05284    return new_msgs;
05285 }

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

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

Referenced by dahdi_cc_callback(), and dahdi_request().

13190 {
13191 #if defined(HAVE_PRI)
13192    if (0 < span) {
13193       /* The channel must be on the specified PRI span. */
13194       if (!p->pri || p->pri->span != span) {
13195          return 0;
13196       }
13197       if (!groupmatch && channelmatch == -1) {
13198          /* Match any group since it only needs to be on the PRI span. */
13199          *groupmatched = 1;
13200          return 1;
13201       }
13202    }
13203 #endif   /* defined(HAVE_PRI) */
13204    /* check group matching */
13205    if (groupmatch) {
13206       if ((p->group & groupmatch) != groupmatch)
13207          /* Doesn't match the specified group, try the next one */
13208          return 0;
13209       *groupmatched = 1;
13210    }
13211    /* Check to see if we have a channel match */
13212    if (channelmatch != -1) {
13213       if (p->channel != channelmatch)
13214          /* Doesn't match the specified channel, try the next one */
13215          return 0;
13216       *channelmatched = 1;
13217    }
13218 
13219    return 1;
13220 }

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

Definition at line 4742 of file chan_dahdi.c.

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

Referenced by conf_del().

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

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

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

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

static int load_module ( void   )  [static]

Definition at line 18796 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_FORMAT_ALAW, ast_format_cap_add(), ast_format_cap_alloc(), ast_format_set(), AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_log(), ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, ast_register_application_xml, ast_channel_tech::capabilities, LOG_ERROR, setup_dahdi(), sig_pri_init_pri(), sig_pri_load(), and sig_ss7_init_linkset().

18797 {
18798    int res;
18799    struct ast_format tmpfmt;
18800 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18801    int y;
18802 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18803 
18804    if (!(dahdi_tech.capabilities = ast_format_cap_alloc())) {
18805       return AST_MODULE_LOAD_FAILURE;
18806    }
18807    ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
18808    ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
18809    ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
18810 
18811 #ifdef HAVE_PRI
18812    memset(pris, 0, sizeof(pris));
18813    for (y = 0; y < NUM_SPANS; y++) {
18814       sig_pri_init_pri(&pris[y].pri);
18815    }
18816    pri_set_error(dahdi_pri_error);
18817    pri_set_message(dahdi_pri_message);
18818    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18819 #ifdef HAVE_PRI_PROG_W_CAUSE
18820    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18821 #endif
18822 #if defined(HAVE_PRI_CCSS)
18823    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18824       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18825       __unload_module();
18826       return AST_MODULE_LOAD_FAILURE;
18827    }
18828 #endif   /* defined(HAVE_PRI_CCSS) */
18829    if (sig_pri_load(
18830 #if defined(HAVE_PRI_CCSS)
18831       dahdi_pri_cc_type
18832 #else
18833       NULL
18834 #endif   /* defined(HAVE_PRI_CCSS) */
18835       )) {
18836       __unload_module();
18837       return AST_MODULE_LOAD_FAILURE;
18838    }
18839 #endif
18840 #if defined(HAVE_SS7)
18841    memset(linksets, 0, sizeof(linksets));
18842    for (y = 0; y < NUM_SPANS; y++) {
18843       sig_ss7_init_linkset(&linksets[y].ss7);
18844    }
18845    ss7_set_error(dahdi_ss7_error);
18846    ss7_set_message(dahdi_ss7_message);
18847 #endif   /* defined(HAVE_SS7) */
18848    res = setup_dahdi(0);
18849    /* Make sure we can register our DAHDI channel type */
18850    if (res)
18851       return AST_MODULE_LOAD_DECLINE;
18852    if (ast_channel_register(&dahdi_tech)) {
18853       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18854       __unload_module();
18855       return AST_MODULE_LOAD_FAILURE;
18856    }
18857 #ifdef HAVE_PRI
18858    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18859 #endif
18860 #if defined(HAVE_SS7)
18861    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18862 #endif   /* defined(HAVE_SS7) */
18863 #ifdef HAVE_OPENR2
18864    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18865    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18866 #endif
18867 
18868    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18869    /* register all the data providers */
18870    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18871    memset(round_robin, 0, sizeof(round_robin));
18872    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18873    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18874    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18875    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18876    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18877    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18878    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18879 #if defined(HAVE_PRI)
18880    ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
18881 #endif   /* defined(HAVE_PRI) */
18882 
18883    ast_cond_init(&ss_thread_complete, NULL);
18884 
18885    return res;
18886 }

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 12293 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_cadence, 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::chan_tech, 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::description, 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_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, strsep(), 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().

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

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

Definition at line 494 of file chan_dahdi.c.

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

00495 {
00496    /* This module does not handle MWI in an event-based manner.  However, it
00497     * subscribes to MWI for each mailbox that is configured so that the core
00498     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00499     * event cache instead of checking the mailbox directly. */
00500 }

static int mwi_send_init ( struct dahdi_pvt pvt  )  [static]

Definition at line 11223 of file chan_dahdi.c.

References ast_callerid_vmwi_generate(), ast_calloc, ast_format_set(), 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().

11224 {
11225    int x;
11226    struct ast_format tmpfmt;
11227 
11228 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11229    /* Determine how this spill is to be sent */
11230    if (pvt->mwisend_rpas) {
11231       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11232       pvt->mwisendactive = 1;
11233    } else if (pvt->mwisend_fsk) {
11234       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11235       pvt->mwisendactive = 1;
11236    } else {
11237       pvt->mwisendactive = 0;
11238       return 0;
11239    }
11240 #else
11241    if (mwisend_rpas) {
11242       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11243    } else {
11244       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11245    }
11246    pvt->mwisendactive = 1;
11247 #endif
11248 
11249    if (pvt->cidspill) {
11250       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11251       ast_free(pvt->cidspill);
11252       pvt->cidspill = NULL;
11253       pvt->cidpos = 0;
11254       pvt->cidlen = 0;
11255    }
11256    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11257    if (!pvt->cidspill) {
11258       pvt->mwisendactive = 0;
11259       return -1;
11260    }
11261    x = DAHDI_FLUSH_BOTH;
11262    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11263    x = 3000;
11264    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11265 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11266    if (pvt->mwisend_fsk) {
11267 #endif
11268       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11269                       ast_format_set(&tmpfmt, AST_LAW(pvt), 0), pvt->cid_name, pvt->cid_num, 0);
11270       pvt->cidpos = 0;
11271 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11272    }
11273 #endif
11274    return 0;
11275 }

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

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

11278 {
11279    struct timeval    now;
11280    int         res;
11281 
11282    /* sanity check to catch if this had been interrupted previously
11283    *  i.e. state says there is more to do but there is no spill allocated
11284    */
11285    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11286       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11287    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11288       /* Normal processing -- Perform mwi send action */
11289       switch ( pvt->mwisend_data.mwisend_current) {
11290       case MWI_SEND_SA:
11291          /* Send the Ring Pulse Signal Alert */
11292          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11293          if (res) {
11294             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11295             goto quit;
11296          }
11297          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11298          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11299          break;
11300       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11301          break;
11302       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11303 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11304          if (pvt->mwisend_fsk) {
11305 #endif
11306             gettimeofday(&now, NULL);
11307             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11308                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11309             }
11310 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11311          } else { /* support for mwisendtype=nofsk */
11312             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11313          }
11314 #endif
11315          break;
11316       case MWI_SEND_SPILL:
11317          /* We read some number of bytes.  Write an equal amount of data */
11318          if(0 < num_read) {
11319             if (num_read > pvt->cidlen - pvt->cidpos)
11320                num_read = pvt->cidlen - pvt->cidpos;
11321             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11322             if (res > 0) {
11323                pvt->cidpos += res;
11324                if (pvt->cidpos >= pvt->cidlen) {
11325                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11326                }
11327             } else {
11328                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11329                goto quit;
11330             }
11331          }
11332          break;
11333       case MWI_SEND_CLEANUP:
11334          /* For now, do nothing */
11335          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11336          break;
11337       default:
11338          /* Should not get here, punt*/
11339          goto quit;
11340       }
11341    }
11342 
11343    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11344       if (pvt->cidspill) {
11345          ast_free(pvt->cidspill);
11346          pvt->cidspill = NULL;
11347          pvt->cidpos = 0;
11348          pvt->cidlen = 0;
11349       }
11350       pvt->mwisendactive = 0;
11351    }
11352    return 0;
11353 quit:
11354    if (pvt->cidspill) {
11355       ast_free(pvt->cidspill);
11356       pvt->cidspill = NULL;
11357       pvt->cidpos = 0;
11358       pvt->cidlen = 0;
11359    }
11360    pvt->mwisendactive = 0;
11361    return -1;
11362 }

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

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

11365 {
11366    int handled = 0;
11367 
11368    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11369       switch (event) {
11370       case DAHDI_EVENT_RINGEROFF:
11371          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11372             handled = 1;
11373 
11374             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11375                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11376                ast_free(pvt->cidspill);
11377                pvt->cidspill = NULL;
11378                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11379                pvt->mwisendactive = 0;
11380             } else {
11381                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11382                gettimeofday(&pvt->mwisend_data.pause, NULL);
11383             }
11384          }
11385          break;
11386       /* Going off hook, I need to punt this spill */
11387       case DAHDI_EVENT_RINGOFFHOOK:
11388          if (pvt->cidspill) {
11389             ast_free(pvt->cidspill);
11390             pvt->cidspill = NULL;
11391             pvt->cidpos = 0;
11392             pvt->cidlen = 0;
11393          }
11394          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11395          pvt->mwisendactive = 0;
11396          break;
11397       case DAHDI_EVENT_RINGERON:
11398       case DAHDI_EVENT_HOOKCOMPLETE:
11399          break;
11400       default:
11401          break;
11402       }
11403    }
11404    return handled;
11405 }

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

Definition at line 11066 of file chan_dahdi.c.

References analog_lib_handles(), analog_ss_thread(), analog_ss_thread_start(), ast_format_set(), 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().

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

static void my_all_subchannels_hungup ( void *  pvt  )  [static]

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

02418 {
02419    struct dahdi_pvt *p = pvt;
02420    int res, law;
02421 
02422    p->faxhandled = 0;
02423    p->didtdd = 0;
02424 
02425    if (p->dsp) {
02426       ast_dsp_free(p->dsp);
02427       p->dsp = NULL;
02428    }
02429 
02430    p->law = p->law_default;
02431    law = p->law_default;
02432    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02433    if (res < 0)
02434       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02435 
02436    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02437 
02438 #if 1
02439    {
02440    int i;
02441    p->owner = NULL;
02442    /* Cleanup owners here */
02443    for (i = 0; i < 3; i++) {
02444       p->subs[i].owner = NULL;
02445    }
02446    }
02447 #endif
02448 
02449    reset_conf(p);
02450    if (num_restart_pending == 0) {
02451       restart_monitor();
02452    }
02453 }

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

Definition at line 2728 of file chan_dahdi.c.

References alloc_sub(), and analogsub_to_dahdisub().

02729 {
02730    struct dahdi_pvt *p = pvt;
02731 
02732    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02733 }

static void my_answer_polarityswitch ( void *  pvt  )  [static]

Definition at line 2966 of file chan_dahdi.c.

References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().

02967 {
02968    struct dahdi_pvt *p = pvt;
02969 
02970    if (!p->answeronpolarityswitch) {
02971       return;
02972    }
02973 
02974    my_set_polarity(pvt, 1);
02975 }

static int my_callwait ( void *  pvt  )  [static]

Definition at line 1919 of file chan_dahdi.c.

References ast_format_set(), 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().

01920 {
01921    struct dahdi_pvt *p = pvt;
01922    struct ast_format tmpfmt;
01923    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01924    if (p->cidspill) {
01925       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01926       ast_free(p->cidspill);
01927    }
01928 
01929    /*
01930     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01931     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01932     */
01933    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01934       return -1;
01935    save_conference(p);
01936    /* Silence */
01937    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01938    if (!p->callwaitrings && p->callwaitingcallerid) {
01939       ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01940       p->callwaitcas = 1;
01941       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01942    } else {
01943       ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01944       p->callwaitcas = 0;
01945       p->cidlen = 2400 + READ_SIZE * 4;
01946    }
01947    p->cidpos = 0;
01948    send_callerid(p);
01949 
01950    return 0;
01951 }

static void my_cancel_cidspill ( void *  pvt  )  [static]

Definition at line 2367 of file chan_dahdi.c.

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

02368 {
02369    struct dahdi_pvt *p = pvt;
02370 
02371    ast_free(p->cidspill);
02372    p->cidspill = NULL;
02373    restore_conference(p);
02374 }

static int my_check_confirmanswer ( void *  pvt  )  [static]

Definition at line 2350 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

02351 {
02352    struct dahdi_pvt *p = pvt;
02353    if (p->confirmanswer) {
02354       return 1;
02355    }
02356 
02357    return 0;
02358 }

static int my_check_for_conference ( void *  pvt  )  [static]

Definition at line 2527 of file chan_dahdi.c.

References check_for_conference().

02528 {
02529    struct dahdi_pvt *p = pvt;
02530    return check_for_conference(p);
02531 }

static int my_check_waitingfordt ( void *  pvt  )  [static]

Definition at line 2333 of file chan_dahdi.c.

References dahdi_pvt::waitingfordt.

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

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

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

02478 {
02479    struct dahdi_pvt *p = pvt;
02480    int needconf = needconference;
02481    int x;
02482    int useslavenative;
02483    struct dahdi_pvt *slave = NULL;
02484 
02485    useslavenative = isslavenative(p, &slave);
02486 
02487    /* If we have a slave, add him to our conference now. or DAX
02488       if this is slave native */
02489    for (x = 0; x < MAX_SLAVES; x++) {
02490       if (p->slaves[x]) {
02491          if (useslavenative)
02492             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02493          else {
02494             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02495             needconf++;
02496          }
02497       }
02498    }
02499    /* If we're supposed to be in there, do so now */
02500    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02501       if (useslavenative)
02502          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02503       else {
02504          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02505          needconf++;
02506       }
02507    }
02508    /* If we have a master, add ourselves to his conference */
02509    if (p->master) {
02510       if (isslavenative(p->master, NULL)) {
02511          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02512       } else {
02513          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02514       }
02515    }
02516    if (!needconf) {
02517       /* Nobody is left (or should be left) in our conference.
02518          Kill it. */
02519       p->confno = -1;
02520    }
02521 
02522    return 0;
02523 }

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

Definition at line 2467 of file chan_dahdi.c.

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

02468 {
02469    struct dahdi_pvt *p = pvt;
02470    int x = analogsub_to_dahdisub(sub);
02471 
02472    return conf_add(p, &p->subs[x], x, 0);
02473 }

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

Definition at line 2457 of file chan_dahdi.c.

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

02458 {
02459    struct dahdi_pvt *p = pvt;
02460    int x = analogsub_to_dahdisub(sub);
02461 
02462    return conf_del(p, &p->subs[x], x);
02463 }

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

Definition at line 2376 of file chan_dahdi.c.

References dahdi_confmute().

02377 {
02378    struct dahdi_pvt *p = pvt;
02379    return dahdi_confmute(p, mute);
02380 }

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

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

09345 {
09346    int sent=0;
09347    int size;
09348    int res;
09349    int fd;
09350    fd = p->subs[idx].dfd;
09351    while (len) {
09352       size = len;
09353       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09354          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09355       res = write(fd, buf, size);
09356       if (res != size) {
09357          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09358          return sent;
09359       }
09360       len -= size;
09361       buf += size;
09362    }
09363    return sent;
09364 }

static void my_deadlock_avoidance_private ( void *  pvt  )  [static]

Definition at line 2139 of file chan_dahdi.c.

References DEADLOCK_AVOIDANCE, and dahdi_pvt::lock.

02140 {
02141    struct dahdi_pvt *p = pvt;
02142 
02143    DEADLOCK_AVOIDANCE(&p->lock);
02144 }

static void my_decrease_ss_count ( void   )  [static]

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

Definition at line 3000 of file chan_dahdi.c.

References ANALOG_DIAL_OP_REPLACE, ANALOG_SUB_REAL, analogsub_to_dahdisub(), ast_channel_name(), 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.

03001 {
03002    int index = analogsub_to_dahdisub(sub);
03003    int res;
03004    struct dahdi_pvt *p = pvt;
03005    struct dahdi_dialoperation ddop;
03006 
03007    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03008       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03009       return -1;
03010    }
03011 
03012    if (sub != ANALOG_SUB_REAL) {
03013       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03014          dop->dialstr, p->channel, sub);
03015       return -1;
03016    }
03017 
03018    ddop.op = DAHDI_DIAL_OP_REPLACE;
03019    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03020 
03021    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03022 
03023    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03024    if (res == -1) {
03025       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", ast_channel_name(p->owner), strerror(errno));
03026    }
03027 
03028    return res;
03029 }

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

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

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

static int my_dsp_reset_and_flush_digits ( void *  pvt  )  [static]

Definition at line 1989 of file chan_dahdi.c.

References ast_dsp_digitreset(), and dahdi_pvt::dsp.

01990 {
01991    struct dahdi_pvt *p = pvt;
01992    if (p->dsp)
01993       ast_dsp_digitreset(p->dsp);
01994 
01995    return 0;
01996 }

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

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

01999 {
02000    struct dahdi_pvt *p = pvt;
02001 
02002    if (p->channel == CHAN_PSEUDO)
02003       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02004 
02005    if (mode == ANALOG_DIGITMODE_DTMF) {
02006       /* If we do hardware dtmf, no need for a DSP */
02007       if (p->hardwaredtmf) {
02008          if (p->dsp) {
02009             ast_dsp_free(p->dsp);
02010             p->dsp = NULL;
02011          }
02012          return 0;
02013       }
02014 
02015       if (!p->dsp) {
02016          p->dsp = ast_dsp_new();
02017          if (!p->dsp) {
02018             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02019             return -1;
02020          }
02021       }
02022 
02023       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02024    } else if (mode == ANALOG_DIGITMODE_MF) {
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       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02033    }
02034    return 0;
02035 }

static int my_flash ( void *  pvt  )  [static]

Definition at line 2925 of file chan_dahdi.c.

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

02926 {
02927    struct dahdi_pvt *p = pvt;
02928    int func = DAHDI_FLASH;
02929    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02930 }

static void my_get_and_handle_alarms ( void *  pvt  )  [static]

Definition at line 2225 of file chan_dahdi.c.

References get_alarms(), and handle_alarms().

02226 {
02227    int res;
02228    struct dahdi_pvt *p = pvt;
02229 
02230    res = get_alarms(p);
02231    handle_alarms(p, res);
02232 }

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

Definition at line 1705 of file chan_dahdi.c.

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

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

static int my_get_event ( void *  pvt  )  [static]

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

02859 {
02860    struct dahdi_pvt *p = pvt;
02861    int res;
02862 
02863    if (p->fake_event) {
02864       res = p->fake_event;
02865       p->fake_event = 0;
02866    } else
02867       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02868 
02869    return dahdievent_to_analogevent(res);
02870 }

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

Definition at line 2395 of file chan_dahdi.c.

References dahdi_pvt::dialstring.

02396 {
02397    struct dahdi_pvt *p = pvt;
02398 
02399    return p->dialstring;
02400 }

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

Definition at line 2234 of file chan_dahdi.c.

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

02235 {
02236    struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02237    if (p)
02238       return p->sig_pvt;
02239    else
02240       return NULL;
02241 }

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

Definition at line 2243 of file chan_dahdi.c.

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

02244 {
02245    struct dahdi_pvt *p = pvt;
02246    int dahdi_sub = analogsub_to_dahdisub(sub);
02247    return p->subs[dahdi_sub].dfd;
02248 }

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

Definition at line 9821 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by analog_ss_thread().

09822 {
09823    char c;
09824 
09825    *str = 0; /* start with empty output buffer */
09826    for (;;)
09827    {
09828       /* Wait for the first digit (up to specified ms). */
09829       c = ast_waitfordigit(chan, ms);
09830       /* if timeout, hangup or error, return as such */
09831       if (c < 1)
09832          return c;
09833       *str++ = c;
09834       *str = 0;
09835       if (strchr(term, c))
09836          return 1;
09837    }
09838 }

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

Definition at line 2055 of file chan_dahdi.c.

References analogsub_to_dahdisub(), ast_async_goto(), ast_channel_lock, ast_channel_name(), 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.

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

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

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

03631 {
03632    struct dahdi_pvt *p = pvt;
03633 
03634    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03635       return;
03636 
03637    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03638       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03639       notify_message(p->mailbox, 1);
03640    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03641       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03642       notify_message(p->mailbox, 0);
03643    }
03644    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03645    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03646    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03647       ast_hangup(chan);
03648       return;
03649    }
03650 }

static void my_hangup_polarityswitch ( void *  pvt  )  [static]

Definition at line 2977 of file chan_dahdi.c.

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

02978 {
02979    struct dahdi_pvt *p = pvt;
02980 
02981    if (!p->hanguponpolarityswitch) {
02982       return;
02983    }
02984 
02985    if (p->answeronpolarityswitch) {
02986       my_set_polarity(pvt, 0);
02987    } else {
02988       my_set_polarity(pvt, 1);
02989    }
02990 }

static int my_has_voicemail ( void *  pvt  )  [static]

Definition at line 2737 of file chan_dahdi.c.

References has_voicemail().

02738 {
02739    struct dahdi_pvt *p = pvt;
02740 
02741    return has_voicemail(p);
02742 }

static int my_have_progressdetect ( void *  pvt  )  [static]

Definition at line 3652 of file chan_dahdi.c.

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

03653 {
03654    struct dahdi_pvt *p = pvt;
03655 
03656    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03657       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03658       return 1;
03659    } else {
03660       /* Don't have progress detection. */
03661       return 0;
03662    }
03663 }

static void my_increase_ss_count ( void   )  [static]

Definition at line 2402 of file chan_dahdi.c.

References ast_mutex_lock, ast_mutex_unlock, and ss_thread_lock.

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

Definition at line 3042 of file chan_dahdi.c.

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

03043 {
03044    struct dahdi_pvt *p = pvt;
03045    int index;
03046    int x;
03047 
03048    index = analogsub_to_dahdisub(sub);
03049 
03050    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03051       ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
03052       return -1;
03053    }
03054 
03055    return x;
03056 }

static int my_is_off_hook ( void *  pvt  )  [static]

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

02873 {
02874    struct dahdi_pvt *p = pvt;
02875    int res;
02876    struct dahdi_params par;
02877 
02878    memset(&par, 0, sizeof(par));
02879 
02880    if (p->subs[SUB_REAL].dfd > -1)
02881       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02882    else {
02883       /* Assume not off hook on CVRS */
02884       res = 0;
02885       par.rxisoffhook = 0;
02886    }
02887    if (res) {
02888       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02889    }
02890 
02891    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02892       /* When "onhook" that means no battery on the line, and thus
02893       it is out of service..., if it's on a TDM card... If it's a channel
02894       bank, there is no telling... */
02895       return (par.rxbits > -1) || par.rxisoffhook;
02896    }
02897 
02898    return par.rxisoffhook;
02899 }

static void my_lock_private ( void *  pvt  )  [static]

Definition at line 2127 of file chan_dahdi.c.

References ast_mutex_lock, and dahdi_pvt::lock.

02128 {
02129    struct dahdi_pvt *p = pvt;
02130    ast_mutex_lock(&p->lock);
02131 }

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

References analogsub_to_dahdisub(), ast_channel_linkedid(), and dahdi_new().

02568 {
02569    struct dahdi_pvt *p = pvt;
02570    int dsub = analogsub_to_dahdisub(sub);
02571 
02572    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? ast_channel_linkedid(requestor) : "");
02573 }

static int my_off_hook ( void *  pvt  )  [static]

Definition at line 2934 of file chan_dahdi.c.

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

02935 {
02936    struct dahdi_pvt *p = pvt;
02937    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02938 }

static int my_on_hook ( void *  pvt  )  [static]

Definition at line 3058 of file chan_dahdi.c.

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

03059 {
03060    struct dahdi_pvt *p = pvt;
03061    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03062 }

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

Definition at line 2744 of file chan_dahdi.c.

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

02745 {
02746    struct dahdi_pvt *p = pvt;
02747    int index;
02748 
02749    index = analogsub_to_dahdisub(sub);
02750 
02751    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02752 }

static int my_ring ( void *  pvt  )  [static]

Definition at line 2918 of file chan_dahdi.c.

References dahdi_ring_phone().

02919 {
02920    struct dahdi_pvt *p = pvt;
02921 
02922    return dahdi_ring_phone(p);
02923 }

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

Definition at line 1953 of file chan_dahdi.c.

References ast_callerid_callwaiting_generate(), ast_callerid_generate(), ast_debug, ast_format_set(), 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.

01954 {
01955    struct dahdi_pvt *p = pvt;
01956    struct ast_format tmpfmt;
01957 
01958    ast_debug(2, "Starting cid spill\n");
01959 
01960    if (p->cidspill) {
01961       ast_log(LOG_WARNING, "cidspill already exists??\n");
01962       ast_free(p->cidspill);
01963    }
01964 
01965    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01966       if (cwcid == 0) {
01967          p->cidlen = ast_callerid_generate(p->cidspill,
01968             caller->id.name.str,
01969             caller->id.number.str,
01970             ast_format_set(&tmpfmt, AST_LAW(p), 0));
01971       } else {
01972          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01973             caller->id.name.str, caller->id.number.str);
01974          p->callwaitcas = 0;
01975          p->cidcwexpire = 0;
01976          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01977             caller->id.name.str,
01978             caller->id.number.str,
01979             ast_format_set(&tmpfmt, AST_LAW(p), 0));
01980          p->cidlen += READ_SIZE * 4;
01981       }
01982       p->cidpos = 0;
01983       p->cid_suppress_expire = 0;
01984       send_callerid(p);
01985    }
01986    return 0;
01987 }

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

Definition at line 2266 of file chan_dahdi.c.

References dahdi_pvt::inalarm.

02267 {
02268    struct dahdi_pvt *p = pvt;
02269 
02270    p->inalarm = in_alarm;
02271 }

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

Definition at line 2250 of file chan_dahdi.c.

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

02251 {
02252    struct dahdi_pvt *p = pvt;
02253 
02254    /* Choose proper cadence */
02255    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02256       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02257          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
02258       *cidrings = cidrings[p->distinctivering - 1];
02259    } else {
02260       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02261          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
02262       *cidrings = p->sendcalleridafter;
02263    }
02264 }

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

Definition at line 2360 of file chan_dahdi.c.

References dahdi_pvt::callwaiting.

02361 {
02362    struct dahdi_pvt *p = pvt;
02363 
02364    p->callwaiting = callwaiting_enable;
02365 }

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

Definition at line 2344 of file chan_dahdi.c.

References dahdi_pvt::confirmanswer.

02345 {
02346    struct dahdi_pvt *p = pvt;
02347    p->confirmanswer = flag;
02348 }

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

Definition at line 2273 of file chan_dahdi.c.

References dahdi_pvt::dialing.

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

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

Definition at line 2904 of file chan_dahdi.c.

References dahdi_disable_ec(), and dahdi_enable_ec().

02905 {
02906    struct dahdi_pvt *p = pvt;
02907 
02908    if (enable)
02909       dahdi_enable_ec(p);
02910    else
02911       dahdi_disable_ec(p);
02912 
02913    return 0;
02914 }

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

Definition at line 2215 of file chan_dahdi.c.

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

02216 {
02217    struct dahdi_pvt *p = pvt;
02218    int idx = analogsub_to_dahdisub(sub);
02219 
02220    p->subs[idx].inthreeway = inthreeway;
02221 }

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

Definition at line 2203 of file chan_dahdi.c.

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

02204 {
02205    struct dahdi_pvt *p = pvt;
02206    int oldval;
02207    int idx = analogsub_to_dahdisub(sub);
02208    
02209    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02210    oldval = p->subs[idx].linear;
02211    p->subs[idx].linear = linear_mode ? 1 : 0;
02212    return oldval;
02213 }

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

Definition at line 2940 of file chan_dahdi.c.

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

02941 {
02942    struct dahdi_pvt *p = pvt;
02943    p->subs[SUB_REAL].needringing = value;
02944 }

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

Definition at line 2388 of file chan_dahdi.c.

References dahdi_pvt::owner.

02389 {
02390    struct dahdi_pvt *p = pvt;
02391 
02392    p->owner = new_owner;
02393 }

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

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

02947 {
02948    struct dahdi_pvt *p = pvt;
02949 
02950    if (p->channel == CHAN_PSEUDO) {
02951       return;
02952    }
02953    p->polarity = value;
02954    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02955 }

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

Definition at line 2382 of file chan_dahdi.c.

References dahdi_pvt::pulsedial.

02383 {
02384    struct dahdi_pvt *p = pvt;
02385    p->pulsedial = flag;
02386 }

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

Definition at line 2316 of file chan_dahdi.c.

References dahdi_pvt::ringt.

02317 {
02318    struct dahdi_pvt *p = pvt;
02319    p->ringt = ringt;
02320 }

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

Definition at line 2322 of file chan_dahdi.c.

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

02323 {
02324    struct dahdi_pvt *p = pvt;
02325 
02326    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02327       ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02328       gettimeofday(&p->waitingfordt, NULL);
02329       ast_setstate(ast, AST_STATE_OFFHOOK);
02330    }
02331 }

static int my_start ( void *  pvt  )  [static]

Definition at line 2992 of file chan_dahdi.c.

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

02993 {
02994    struct dahdi_pvt *p = pvt;
02995    int x = DAHDI_START;
02996 
02997    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02998 }

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

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

01681 {
01682    struct dahdi_pvt *p = pvt;
01683    int index = SUB_REAL;
01684    p->cs = callerid_new(cid_signalling);
01685    if (!p->cs) {
01686       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01687       return -1;
01688    }
01689    bump_gains(p);
01690    dahdi_setlinear(p->subs[index].dfd, 0);
01691 
01692    return 0;
01693 }

static void my_start_polarityswitch ( void *  pvt  )  [static]

Definition at line 2957 of file chan_dahdi.c.

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

02958 {
02959    struct dahdi_pvt *p = pvt;
02960 
02961    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02962       my_set_polarity(pvt, 0);
02963    }
02964 }

static int my_stop_callwait ( void *  pvt  )  [static]

Definition at line 1905 of file chan_dahdi.c.

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

01906 {
01907    struct dahdi_pvt *p = pvt;
01908    p->callwaitingrepeat = 0;
01909    p->cidcwexpire = 0;
01910    p->cid_suppress_expire = 0;
01911 
01912    return 0;
01913 }

static int my_stop_cid_detect ( void *  pvt  )  [static]

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

01696 {
01697    struct dahdi_pvt *p = pvt;
01698    int index = SUB_REAL;
01699    if (p->cs)
01700       callerid_free(p->cs);
01701    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01702    return 0;
01703 }

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

02534 {
02535    struct dahdi_pvt *p = pvt;
02536    int da, db;
02537    int tchan;
02538    int tinthreeway;
02539 
02540    da = analogsub_to_dahdisub(a);
02541    db = analogsub_to_dahdisub(b);
02542 
02543    tchan = p->subs[da].chan;
02544    p->subs[da].chan = p->subs[db].chan;
02545    p->subs[db].chan = tchan;
02546 
02547    tinthreeway = p->subs[da].inthreeway;
02548    p->subs[da].inthreeway = p->subs[db].inthreeway;
02549    p->subs[db].inthreeway = tinthreeway;
02550 
02551    p->subs[da].owner = ast_a;
02552    p->subs[db].owner = ast_b;
02553 
02554    if (ast_a)
02555       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02556    if (ast_b)
02557       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02558 
02559    wakeup_sub(p, a);
02560    wakeup_sub(p, b);
02561 
02562    return;
02563 }

static int my_train_echocanceller ( void *  pvt  )  [static]

Definition at line 3033 of file chan_dahdi.c.

References dahdi_train_ec().

03034 {
03035    struct dahdi_pvt *p = pvt;
03036 
03037    dahdi_train_ec(p);
03038 
03039    return 0;
03040 }

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

Definition at line 2719 of file chan_dahdi.c.

References analogsub_to_dahdisub(), and unalloc_sub().

02720 {
02721    struct dahdi_pvt *p = pvt;
02722 
02723    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02724 }

static void my_unlock_private ( void *  pvt  )  [static]

Definition at line 2133 of file chan_dahdi.c.

References ast_mutex_unlock, and dahdi_pvt::lock.

02134 {
02135    struct dahdi_pvt *p = pvt;
02136    ast_mutex_unlock(&p->lock);
02137 }

static int my_wait_event ( void *  pvt  )  [static]

Definition at line 2851 of file chan_dahdi.c.

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

02852 {
02853    struct dahdi_pvt *p = pvt;
02854 
02855    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02856 }

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

Definition at line 2039 of file chan_dahdi.c.

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

02040 {
02041    struct dahdi_pvt *p = pvt;
02042    int index = analogsub_to_dahdisub(sub);
02043    if (index != SUB_REAL) {
02044       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02045    }
02046    return dahdi_wink(p, index);
02047 }

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

References AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_safe_system(), ast_strdupa, ast_strlen_zero(), context, mailbox, and strsep().

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

03602 {
03603    char s[sizeof(mwimonitornotify) + 80];
03604    struct ast_event *event;
03605    char *mailbox, *context;
03606 
03607    /* Strip off @default */
03608    context = mailbox = ast_strdupa(mailbox_full);
03609    strsep(&context, "@");
03610    if (ast_strlen_zero(context))
03611       context = "default";
03612 
03613    if (!(event = ast_event_new(AST_EVENT_MWI,
03614          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03615          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03616          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03617          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03618          AST_EVENT_IE_END))) {
03619       return;
03620    }
03621 
03622    ast_event_queue_and_cache(event);
03623 
03624    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03625       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03626       ast_safe_system(s);
03627    }
03628 }

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

Definition at line 7056 of file chan_dahdi.c.

References ast_log(), and LOG_WARNING.

Referenced by dahdi_func_write(), and process_dahdi().

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

static void parse_busy_pattern ( struct ast_variable v,
struct ast_dsp_busy_pattern busy_cadence 
) [static]

Definition at line 17105 of file chan_dahdi.c.

References ast_log(), ast_dsp_busy_pattern::length, ast_variable::lineno, LOG_ERROR, ast_dsp_busy_pattern::pattern, and ast_variable::value.

Referenced by process_dahdi().

17106 {
17107    int count_pattern = 0;
17108    int norval = 0;
17109    char *temp = NULL;
17110 
17111    for (; ;) {
17112       /* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
17113       if(!sscanf(v->value, "%30d", &norval) && count_pattern == 0) { 
17114          ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17115          break;
17116       }
17117 
17118       busy_cadence->pattern[count_pattern] = norval; 
17119       
17120       count_pattern++;
17121       if (count_pattern == 4) {
17122          break;
17123       }
17124 
17125       temp = strchr(v->value, ',');
17126       if (temp == NULL) {
17127          break;
17128       }
17129       v->value = temp + 1;
17130    }
17131    busy_cadence->length = count_pattern;
17132 
17133    if (count_pattern % 2 != 0) { 
17134       /* The pattern length must be divisible by two */
17135       ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17136    }
17137    
17138 }

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

Definition at line 16881 of file chan_dahdi.c.

References string_replace().

Referenced by build_channels().

16882 {
16883    char *p;
16884 
16885    if ((p = strrchr(chanstr, '!')) == NULL) {
16886       *subdir = NULL;
16887       return chanstr;
16888    }
16889    *p++ = '\0';
16890    string_replace(chanstr, '!', '/');
16891    *subdir = chanstr;
16892    return p;
16893 }

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

Definition at line 17140 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_debug, 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_cadence, 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::description, 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_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(), parse_busy_pattern(), 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_PRI_MOH_SIGNALING_MOH, SIG_PRI_MOH_SIGNALING_NOTIFY, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, SIG_SS7, dahdi_chan_conf::smdi_port, dahdi_pvt::span, SS7_NAI_DYNAMIC, strcasestr(), dahdi_pvt::stripmsd, strsep(), 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().

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

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

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

16969 {
16970    char *parse = ast_strdupa(data);
16971    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16972    unsigned int param_count;
16973    unsigned int x;
16974 
16975    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16976       return;
16977 
16978    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16979 
16980    /* first parameter is tap length, process it here */
16981 
16982    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16983 
16984    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16985       confp->chan.echocancel.head.tap_length = x;
16986    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16987       confp->chan.echocancel.head.tap_length = 128;
16988 
16989    /* now process any remaining parameters */
16990 
16991    for (x = 1; x < param_count; x++) {
16992       struct {
16993          char *name;
16994          char *value;
16995       } param;
16996 
16997       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16998          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16999          continue;
17000       }
17001 
17002       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17003          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
17004          continue;
17005       }
17006 
17007       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17008 
17009       if (param.value) {
17010          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17011             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
17012             continue;
17013          }
17014       }
17015       confp->chan.echocancel.head.param_count++;
17016    }
17017 }

static int reload ( void   )  [static]

Definition at line 19010 of file chan_dahdi.c.

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

19011 {
19012    int res = 0;
19013 
19014    res = setup_dahdi(1);
19015    if (res) {
19016       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
19017       return -1;
19018    }
19019    return 0;
19020 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

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

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

static int restart_monitor ( void   )  [static]

Definition at line 11958 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, LOG_WARNING, and monlock.

Referenced by dahdi_hangup(), dahdi_request(), h323_reload(), load_module(), mgcp_reload(), mgcp_request(), my_all_subchannels_hungup(), oh323_request(), phone_hangup(), phone_request(), setup_dahdi_int(), sip_reload(), sip_request_call(), unistim_reload(), and unistim_request().

11959 {
11960    /* If we're supposed to be stopped -- stay stopped */
11961    if (monitor_thread == AST_PTHREADT_STOP)
11962       return 0;
11963    ast_mutex_lock(&monlock);
11964    if (monitor_thread == pthread_self()) {
11965       ast_mutex_unlock(&monlock);
11966       ast_log(LOG_WARNING, "Cannot kill myself\n");
11967       return -1;
11968    }
11969    if (monitor_thread != AST_PTHREADT_NULL) {
11970       /* Wake up the thread */
11971       pthread_kill(monitor_thread, SIGURG);
11972    } else {
11973       /* Start a new monitor */
11974       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11975          ast_mutex_unlock(&monlock);
11976          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11977          return -1;
11978       }
11979    }
11980    ast_mutex_unlock(&monlock);
11981    return 0;
11982 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

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

05230 {
05231    int res;
05232    if (p->saveconf.confmode) {
05233       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05234       p->saveconf.confmode = 0;
05235       if (res) {
05236          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05237          return -1;
05238       }
05239       ast_debug(1, "Restored conferencing\n");
05240    }
05241    return 0;
05242 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

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

05137 {
05138    int res;
05139 
05140    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05141    if (res) {
05142       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05143       return -1;
05144    }
05145 
05146    return 0;
05147 }

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

Definition at line 6147 of file chan_dahdi.c.

References ast_channel_name(), 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().

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

static int save_conference ( struct dahdi_pvt p  )  [static]

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

05204 {
05205    struct dahdi_confinfo c;
05206    int res;
05207    if (p->saveconf.confmode) {
05208       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05209       return -1;
05210    }
05211    p->saveconf.chan = 0;
05212    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05213    if (res) {
05214       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05215       p->saveconf.confmode = 0;
05216       return -1;
05217    }
05218    memset(&c, 0, sizeof(c));
05219    c.confmode = DAHDI_CONF_NORMAL;
05220    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05221    if (res) {
05222       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05223       return -1;
05224    }
05225    ast_debug(1, "Disabled conferencing\n");
05226    return 0;
05227 }

static int send_callerid ( struct dahdi_pvt p  )  [static]

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

05290 {
05291    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05292    int res;
05293    /* Take out of linear mode if necessary */
05294    if (p->subs[SUB_REAL].linear) {
05295       p->subs[SUB_REAL].linear = 0;
05296       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05297    }
05298    while (p->cidpos < p->cidlen) {
05299       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05300       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05301       if (res < 0) {
05302          if (errno == EAGAIN)
05303             return 0;
05304          else {
05305             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05306             return -1;
05307          }
05308       }
05309       if (!res)
05310          return 0;
05311       p->cidpos += res;
05312    }
05313    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05314    ast_free(p->cidspill);
05315    p->cidspill = NULL;
05316    if (p->callwaitcas) {
05317       /* Wait for CID/CW to expire */
05318       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05319       p->cid_suppress_expire = p->cidcwexpire;
05320    } else
05321       restore_conference(p);
05322    return 0;
05323 }

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

Definition at line 5244 of file chan_dahdi.c.

References ast_callerid_callwaiting_generate(), ast_format_set(), 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().

05245 {
05246    struct ast_format tmpfmt;
05247 
05248    p->callwaitcas = 0;
05249    p->cidcwexpire = 0;
05250    p->cid_suppress_expire = 0;
05251    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05252       return -1;
05253    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05254    /* Make sure we account for the end */
05255    p->cidlen += READ_SIZE * 4;
05256    p->cidpos = 0;
05257    send_callerid(p);
05258    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05259    return 0;
05260 }

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

Definition at line 5117 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

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

05118 {
05119    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05120 }

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

Definition at line 5100 of file chan_dahdi.c.

References ast_debug, errno, and fill_rxgain().

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

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

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

Definition at line 5083 of file chan_dahdi.c.

References ast_debug, errno, and fill_txgain().

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

05084 {
05085    struct dahdi_gains g;
05086    int res;
05087 
05088    memset(&g, 0, sizeof(g));
05089    res = ioctl(fd, DAHDI_GETGAINS, &g);
05090    if (res) {
05091       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05092       return res;
05093    }
05094 
05095    fill_txgain(&g, gain, drc, law);
05096 
05097    return ioctl(fd, DAHDI_SETGAINS, &g);
05098 }

static int setup_dahdi ( int  reload  )  [static]

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

18621 {
18622    int res;
18623    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18624    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18625    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18626 
18627    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18628       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18629    } else {
18630       res = -1;
18631    }
18632    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18633    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18634    ast_cc_config_params_destroy(conf.chan.cc_params);
18635 
18636    return res;
18637 }

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 18333 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, iflock, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sig_ss7_linkset::master, ast_variable::name, ast_variable::next, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_dahdi(), restart_monitor(), sig_pri_start_pri(), sig_ss7_linkset::ss7, ss7_linkset(), and ast_variable::value.

Referenced by setup_dahdi().

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

static int sigtype_to_signalling ( int  sigtype  )  [static]

Definition at line 12242 of file chan_dahdi.c.

Referenced by mkintf().

12243 {
12244    return sigtype;
12245 }

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

Definition at line 16872 of file chan_dahdi.c.

Referenced by parse_spanchan().

16873 {
16874    for (; *str; str++) {
16875       if (*str == char1) {
16876          *str = char2;
16877       }
16878    }
16879 }

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

Definition at line 4275 of file chan_dahdi.c.

References ast_channel_set_fd(), ast_debug, dahdi_subchannel::chan, dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().

Referenced by analog_ss_thread(), attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), HandleCallOutgoing(), and unistim_hangup().

04276 {
04277    int tchan;
04278    int tinthreeway;
04279    struct ast_channel *towner;
04280 
04281    ast_debug(1, "Swapping %d and %d\n", a, b);
04282 
04283    tchan = p->subs[a].chan;
04284    towner = p->subs[a].owner;
04285    tinthreeway = p->subs[a].inthreeway;
04286 
04287    p->subs[a].chan = p->subs[b].chan;
04288    p->subs[a].owner = p->subs[b].owner;
04289    p->subs[a].inthreeway = p->subs[b].inthreeway;
04290 
04291    p->subs[b].chan = tchan;
04292    p->subs[b].owner = towner;
04293    p->subs[b].inthreeway = tinthreeway;
04294 
04295    if (p->subs[a].owner)
04296       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04297    if (p->subs[b].owner)
04298       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04299    wakeup_sub(p, a);
04300    wakeup_sub(p, b);
04301 }

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

Definition at line 4421 of file chan_dahdi.c.

References ast_debug, ast_log(), dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_subchannel::curconf, dahdi_close_sub(), dahdi_subchannel::inthreeway, dahdi_subchannel::linear, LOG_WARNING, dahdi_subchannel::owner, dahdi_pvt::polarity, POLARITY_IDLE, and dahdi_pvt::subs.

Referenced by analog_ss_thread(), attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), my_unallocate_sub(), and unistim_hangup().

04422 {
04423    if (!x) {
04424       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04425       return -1;
04426    }
04427    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04428    dahdi_close_sub(p, x);
04429    p->subs[x].linear = 0;
04430    p->subs[x].chan = 0;
04431    p->subs[x].owner = NULL;
04432    p->subs[x].inthreeway = 0;
04433    p->polarity = POLARITY_IDLE;
04434    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04435    return 0;
04436 }

static int unload_module ( void   )  [static]

Definition at line 16856 of file chan_dahdi.c.

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

16857 {
16858 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16859    int y;
16860 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16861 #ifdef HAVE_PRI
16862    for (y = 0; y < NUM_SPANS; y++)
16863       ast_mutex_destroy(&pris[y].pri.lock);
16864 #endif
16865 #if defined(HAVE_SS7)
16866    for (y = 0; y < NUM_SPANS; y++)
16867       ast_mutex_destroy(&linksets[y].ss7.lock);
16868 #endif   /* defined(HAVE_SS7) */
16869    return __unload_module();
16870 }

static int update_conf ( struct dahdi_pvt p  )  [static]

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

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

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

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

03789 {
03790    dahdi_lock_sub_owner(p, a);
03791    if (p->subs[a].owner) {
03792       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03793       ast_channel_unlock(p->subs[a].owner);
03794    }
03795 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = tdesc , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_smdi", } [static]

Definition at line 19032 of file chan_dahdi.c.

int alarm

Definition at line 4568 of file chan_dahdi.c.

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

Referenced by alarm2str().

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

Definition at line 420 of file chan_dahdi.c.

Definition at line 19032 of file chan_dahdi.c.

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

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

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

Definition at line 355 of file chan_dahdi.c.

Definition at line 3665 of file chan_dahdi.c.

Initial value:

Definition at line 18780 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

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

Initial value:

Definition at line 18775 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 1527 of file chan_dahdi.c.

Initial value:

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

char defaultcic[64] = "" [static]

Definition at line 428 of file chan_dahdi.c.

char defaultozz[64] = "" [static]

Definition at line 429 of file chan_dahdi.c.

int distinctiveringaftercid = 0 [static]

Definition at line 440 of file chan_dahdi.c.

int dtmfcid_level = 256 [static]

Definition at line 445 of file chan_dahdi.c.

const char* const events[] [static]

Definition at line 4545 of file chan_dahdi.c.

int firstdigittimeout = 16000 [static]

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

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

struct ast_jb_conf global_jbconf [static]

Definition at line 312 of file chan_dahdi.c.

int ifcount = 0 [static]

Definition at line 469 of file chan_dahdi.c.

struct dahdi_pvt* ifend = NULL [static]

Main interface list end

Definition at line 1327 of file chan_dahdi.c.

struct dahdi_pvt* iflist = NULL [static]

Main interface list start

Definition at line 1326 of file chan_dahdi.c.

Referenced by __oh323_destroy(), __unload_module(), do_monitor(), find_call_locked(), load_module(), oh323_alloc(), phone_request(), and unload_module().

ast_mutex_t iflock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

const char* const lbostr[] [static]

Definition at line 291 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 463 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 481 of file chan_dahdi.c.

ast_mutex_t monlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

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

Definition at line 477 of file chan_dahdi.c.

Referenced by __unload_module(), dahdi_restart(), do_monitor(), restart_monitor(), and unload_module().

int mwilevel = 512 [static]

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

int mwisend_rpas = 0 [static]

Definition at line 434 of file chan_dahdi.c.

char* name

Definition at line 4569 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 398 of file chan_dahdi.c.

int num_restart_pending = 0 [static]

Definition at line 486 of file chan_dahdi.c.

int numbufs = 4 [static]

Definition at line 442 of file chan_dahdi.c.

char progzone[10] = "" [static]

Definition at line 437 of file chan_dahdi.c.

int report_alarms = REPORT_CHANNEL_ALARMS [static]

Definition at line 449 of file chan_dahdi.c.

ast_mutex_t restart_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

Definition at line 484 of file chan_dahdi.c.

Referenced by dahdi_restart().

int ringt_base = DEFAULT_RINGT [static]

Configured ring timeout base.

Note:
Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.

Definition at line 542 of file chan_dahdi.c.

struct dahdi_pvt* round_robin[32] [static]

Round robin search locations.

Definition at line 3735 of file chan_dahdi.c.

Definition at line 482 of file chan_dahdi.c.

int ss_thread_count = 0 [static]

Definition at line 485 of file chan_dahdi.c.

ast_mutex_t ss_thread_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

const char* const subnames[] [static]

Initial value:

 {
   "Real",
   "Callwait",
   "Threeway"
}

Definition at line 653 of file chan_dahdi.c.

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

Definition at line 334 of file chan_dahdi.c.

int usedistinctiveringdetection = 0 [static]

Definition at line 439 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 399 of file chan_dahdi.c.


Generated on Sat Feb 11 06:34:32 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6