Asterisk - The Open Source Telephony Project GIT-master-a358458
Data Structures | Macros | Functions | Variables
chan_dahdi.c File Reference

DAHDI for Pseudo TDM. More...

#include "asterisk.h"
#include <sys/sysmacros.h>
#include <signal.h>
#include <sys/stat.h>
#include <math.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/pickup.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/say.h"
#include "asterisk/tdd.h"
#include "asterisk/mwi.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/devicestate.h"
#include "asterisk/paths.h"
#include "asterisk/ccss.h"
#include "asterisk/features_config.h"
#include "asterisk/bridge.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/parking.h"
#include "asterisk/format_cache.h"
#include "chan_dahdi.h"
#include "dahdi/bridge_native_dahdi.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_starting_point
 
struct  mwi_thread_data
 

Macros

#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 DEFAULT_CIDRINGS   1
 Typically, how many rings before we should send Caller*ID. More...
 
#define DEFAULT_DIALTONE_DETECT_TIMEOUT   ((10000 * 8) / READ_SIZE)
 
#define DEFAULT_RINGT   ((8000 * 8) / READ_SIZE)
 
#define END_SILENCE_LEN   400
 
#define FORMAT   "%7s %4d %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"
 
#define FORMAT   "%4d %-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
 
#define FORMAT2   "%7s %4s %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"
 
#define FORMAT2   "%4s %-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
 
#define gen_pvt_field_callback(type, field)
 
#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 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. More...
 
#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 SMDI_MD_WAIT_TIMEOUT   1500 /* 1.5 seconds */
 
#define TRAILER_MS   5
 
#define TRANSFER   0
 

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)
 
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_dahdishowstatus (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 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)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int attempt_transfer (struct dahdi_pvt *p)
 
static int available (struct dahdi_pvt **pvt, int is_specific_channel)
 
static void build_alarm_info (char *restrict alarmstr, struct dahdi_spaninfo *spaninfo)
 
static int build_channels (struct dahdi_chan_conf *conf, const char *value, int reload, int lineno)
 
static int bump_gains (struct dahdi_pvt *p)
 
static int calc_energy (const unsigned char *buf, int len, struct ast_format *law)
 
static int canmatch_featurecode (const char *pickupexten, 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 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(). More...
 
static struct dahdi_chan_conf dahdi_chan_conf_default (void)
 
static void dahdi_close (int fd)
 
static void dahdi_close_sub (struct dahdi_pvt *chan_pvt, int sub_num)
 
void dahdi_conf_update (struct dahdi_pvt *p)
 
static int dahdi_confmute (struct dahdi_pvt *p, int muted)
 
static int dahdi_create_channel_range (int start, int end)
 
static char * dahdi_create_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void dahdi_destroy_channel_range (int start, int end)
 
static char * dahdi_destroy_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int dahdi_devicestate (const char *data)
 
static int dahdi_dial_str (struct dahdi_pvt *pvt, int operation, const char *dial_str)
 
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 int dahdi_dnd (struct dahdi_pvt *dahdichan, int flag)
 enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel More...
 
void dahdi_dtmf_detect_disable (struct dahdi_pvt *p)
 
void dahdi_dtmf_detect_enable (struct dahdi_pvt *p)
 
void dahdi_ec_disable (struct dahdi_pvt *p)
 
void dahdi_ec_enable (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. More...
 
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_lock_sub_owner (struct dahdi_pvt *pvt, int sub_idx)
 
void dahdi_master_slave_link (struct dahdi_pvt *slave, struct dahdi_pvt *master)
 
void dahdi_master_slave_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
 
static struct ast_channeldahdi_new (struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid)
 
static struct ast_channeldahdi_new_callid_clean (struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid, int callid_created)
 
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_assigned_ids *assignedids, 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_mwi (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 void dahdi_softhangup_all (void)
 
static void dahdi_train_ec (struct dahdi_pvt *p)
 
static int dahdi_wait_event (int fd)
 Avoid the silly dahdi_waitevent which ignores a bunch of events. More...
 
static int dahdi_wink (struct dahdi_pvt *p, int index)
 
static int dahdi_write (struct ast_channel *ast, struct ast_frame *frame)
 
static struct ast_manager_event_blobdahdichannel_to_ami (struct stasis_message *msg)
 
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 digit_to_dtmfindex (char digit)
 
static void * do_monitor (void *data)
 
static int drc_sample (int sample, float drc)
 
static struct dahdi_pvtduplicate_pseudo (struct dahdi_pvt *src)
 
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 struct dahdi_pvtfxo_pvt (struct ast_channel *chan)
 Return DAHDI pivot if channel is FXO signalled. More...
 
 gen_pvt_field_callback (int, firstdigit_timeout)
 
 gen_pvt_field_callback (int, interdigit_timeout)
 
 gen_pvt_field_callback (int, matchdigit_timeout)
 
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)
 Load the module. More...
 
static struct dahdi_pvtmkintf (int channel, const struct dahdi_chan_conf *conf, int reloading)
 
static void monitor_pfds_clean (void *arg)
 
static int mwi_send_init (struct dahdi_pvt *pvt)
 
static int mwi_send_process_buffer (struct dahdi_pvt *pvt, int num_read)
 
static int mwi_send_process_event (struct dahdi_pvt *pvt, int event)
 
static void * mwi_thread (void *data)
 
static void my_all_subchannels_hungup (void *pvt)
 
static int my_allocate_sub (void *pvt, enum analog_sub analogsub)
 
static void my_answer_polarityswitch (void *pvt)
 
static int my_callwait (void *pvt)
 
static void my_cancel_cidspill (void *pvt)
 
static int my_check_confirmanswer (void *pvt)
 
static int my_check_for_conference (void *pvt)
 
static int my_check_waitingfordt (void *pvt)
 
static int my_complete_conference_update (void *pvt, int needconference)
 
static int my_conf_add (void *pvt, enum analog_sub sub)
 
static int my_conf_del (void *pvt, enum analog_sub sub)
 
static int my_confmute (void *pvt, int mute)
 
static int my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
 
static void my_deadlock_avoidance_private (void *pvt)
 
static void my_decrease_ss_count (void)
 
static int my_dial_digits (void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
 
static int my_distinctive_ring (struct ast_channel *chan, void *pvt, int idx, int *ringdata)
 
static int my_dsp_reset_and_flush_digits (void *pvt)
 
static int my_dsp_set_digitmode (void *pvt, enum analog_dsp_digitmode mode)
 
static int my_flash (void *pvt)
 
static void my_get_and_handle_alarms (void *pvt)
 
static int my_get_callerid (void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
 
static int my_get_event (void *pvt)
 
static const char * my_get_orig_dialstring (void *pvt)
 
static void * my_get_sigpvt_bridged_channel (struct ast_channel *chan)
 
static int my_get_sub_fd (void *pvt, enum analog_sub sub)
 
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
 
static void my_handle_dtmf (void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
 
static void my_handle_notify_message (struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
 
static void my_hangup_polarityswitch (void *pvt)
 
static int my_has_voicemail (void *pvt)
 
static int my_have_progressdetect (void *pvt)
 
static void my_increase_ss_count (void)
 
static int my_is_dialing (void *pvt, enum analog_sub sub)
 
static int my_is_off_hook (void *pvt)
 
static void my_lock_private (void *pvt)
 
static struct ast_channelmy_new_analog_ast_channel (void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
 
static int my_off_hook (void *pvt)
 
static int my_on_hook (void *pvt)
 
static int my_play_tone (void *pvt, enum analog_sub sub, enum analog_tone tone)
 
static int my_ring (void *pvt)
 
static int my_send_callerid (void *pvt, int cwcid, struct ast_party_caller *caller)
 
static void my_set_alarm (void *pvt, int in_alarm)
 
static void my_set_cadence (void *pvt, int *cid_rings, struct ast_channel *ast)
 
static void my_set_callwaiting (void *pvt, int callwaiting_enable)
 
static void my_set_confirmanswer (void *pvt, int flag)
 
static void my_set_dialing (void *pvt, int is_dialing)
 
static int my_set_echocanceller (void *pvt, int enable)
 
static void my_set_inthreeway (void *pvt, enum analog_sub sub, int inthreeway)
 
static int my_set_linear_mode (void *pvt, enum analog_sub sub, int linear_mode)
 
static void my_set_needringing (void *pvt, int value)
 
static void my_set_new_owner (void *pvt, struct ast_channel *new_owner)
 
static void my_set_outgoing (void *pvt, int is_outgoing)
 
static void my_set_polarity (void *pvt, int value)
 
static void my_set_pulsedial (void *pvt, int flag)
 
static void my_set_ringtimeout (void *pvt, int ringt)
 
static void my_set_waitingfordt (void *pvt, struct ast_channel *ast)
 
static int my_start (void *pvt)
 
static int my_start_cid_detect (void *pvt, int cid_signalling)
 
static void my_start_polarityswitch (void *pvt)
 
static int my_stop_callwait (void *pvt)
 
static int my_stop_cid_detect (void *pvt)
 
static void my_swap_subchannels (void *pvt, enum analog_sub a, struct ast_channel *ast_a, enum analog_sub b, struct ast_channel *ast_b)
 
static int my_train_echocanceller (void *pvt)
 
static int my_unallocate_sub (void *pvt, enum analog_sub analogsub)
 
static void my_unlock_private (void *pvt)
 
static int my_wait_event (void *pvt)
 
static int my_wink (void *pvt, enum analog_sub sub)
 
static void notify_message (char *mailbox, int thereornot)
 Send MWI state change. More...
 
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 int polarity_read (struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)
 
static int polarity_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 
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 void publish_channel_alarm (int channel, const char *alarm_txt)
 
static void publish_channel_alarm_clear (int channel)
 
static void publish_dahdichannel (struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
 Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages. More...
 
static void publish_dnd_state (int channel, const char *status)
 
static void publish_span_alarm (int span, const char *alarm_txt)
 
static void publish_span_alarm_clear (int span)
 
static void release_doomed_pris (void)
 
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 set_hwgain (int fd, float gain, int tx_direction)
 
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)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (dahdichannel_type,.to_ami=dahdichannel_to_ami,)
 
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 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, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .requires = "ccss", .optional_modules = "res_smdi", }
 
struct {
   int   alarm
 
   char *   name
 
alarms []
 
struct analog_callback analog_callbacks
 
static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}
 
static const 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. More...
 
static const char config [] = "chan_dahdi.conf"
 
static struct ast_cli_entry dahdi_cli []
 
static struct ast_channel_tech dahdi_tech
 
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 struct ast_jb_conf global_jbconf
 
static int has_pseudo
 
static int ifcount = 0
 
static struct dahdi_pvtifend = NULL
 
static struct dahdi_pvtiflist = NULL
 
static ast_mutex_t iflock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Protect the interface list (of dahdi_pvt's) More...
 
static const char *const lbostr []
 
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. More...
 
static ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. More...
 
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 struct ast_custom_function polarity_function
 
static char progzone [10] = ""
 
static int report_alarms = REPORT_CHANNEL_ALARMS
 
static ast_mutex_t restart_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base. More...
 
static struct dahdi_pvtround_robin [64]
 
static ast_cond_t ss_thread_complete
 
static int ss_thread_count = 0
 
static ast_mutex_t ss_thread_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
const char *const subnames []
 
static const char tdesc [] = "DAHDI Telephony"
 
static int usedistinctiveringdetection = 0
 
static int user_has_defined_cadences = 0
 

Detailed Description

DAHDI for Pseudo TDM.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

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.

Todo:
Deprecate the "musiconhold" configuration option post 1.4

Definition in file chan_dahdi.c.

Macro Definition Documentation

◆ ASCII_BYTES_PER_CHAR

#define ASCII_BYTES_PER_CHAR   80

◆ AST_LAW

#define AST_LAW (   p)    (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw)

Definition at line 642 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX

#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)

Definition at line 682 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX_INCOMING

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 681 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX_OUTGOING

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 680 of file chan_dahdi.c.

◆ CALLPROGRESS_PROGRESS

#define CALLPROGRESS_PROGRESS   1

Definition at line 679 of file chan_dahdi.c.

◆ CALLWAITING_REPEAT_SAMPLES

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

10,000 ms

Definition at line 800 of file chan_dahdi.c.

◆ CALLWAITING_SILENT_SAMPLES

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

300 ms

Definition at line 799 of file chan_dahdi.c.

◆ CALLWAITING_SUPPRESS_SAMPLES

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

100 ms

Definition at line 801 of file chan_dahdi.c.

◆ CANBUSYDETECT

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

Definition at line 714 of file chan_dahdi.c.

◆ CANPROGRESSDETECT

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

Definition at line 715 of file chan_dahdi.c.

◆ CHAN_PSEUDO

#define CHAN_PSEUDO   -2

Definition at line 677 of file chan_dahdi.c.

◆ CIDCW_EXPIRE_SAMPLES

#define CIDCW_EXPIRE_SAMPLES   ((500 * 8) / READ_SIZE)

500 ms

Definition at line 802 of file chan_dahdi.c.

◆ DEFAULT_CIDRINGS

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

◆ DEFAULT_DIALTONE_DETECT_TIMEOUT

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

10,000 ms

Definition at line 805 of file chan_dahdi.c.

◆ DEFAULT_RINGT

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

8,000 ms

Definition at line 804 of file chan_dahdi.c.

◆ END_SILENCE_LEN

#define END_SILENCE_LEN   400

◆ FORMAT [1/2]

#define FORMAT   "%7s %4d %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"

◆ FORMAT [2/2]

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

◆ FORMAT2 [1/2]

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

◆ FORMAT2 [2/2]

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

◆ gen_pvt_field_callback

#define gen_pvt_field_callback (   type,
  field 
)
Value:
static type my_get_##field(void *pvt) \
{ \
struct dahdi_pvt *p = pvt; \
return p->field; \
}
static const char type[]
Definition: chan_ooh323.c:109

Definition at line 3591 of file chan_dahdi.c.

◆ GET_CHANNEL

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

Definition at line 1180 of file chan_dahdi.c.

◆ HANGUP

#define HANGUP   1

Definition at line 16725 of file chan_dahdi.c.

◆ HEADER_LEN

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

◆ HEADER_MS

#define HEADER_MS   50

◆ ISTRUNK

#define ISTRUNK (   p)
Value:
((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
(p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
#define SIG_FXSLS
Definition: chan_dahdi.h:786
#define SIG_FXSKS
Definition: chan_dahdi.h:788
#define SIG_FXSGS
Definition: chan_dahdi.h:787
#define SIG_PRI
Definition: chan_dahdi.h:800

Definition at line 711 of file chan_dahdi.c.

◆ MASK_AVAIL

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 796 of file chan_dahdi.c.

◆ MASK_INUSE

#define MASK_INUSE   (1 << 1)

Channel currently in use

Definition at line 797 of file chan_dahdi.c.

◆ MAX_CHANLIST_LEN

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

◆ MIN_MS_SINCE_FLASH

#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

Definition at line 803 of file chan_dahdi.c.

◆ NEED_MFDETECT

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

Definition at line 646 of file chan_dahdi.c.

◆ NUM_CADENCE_MAX

#define NUM_CADENCE_MAX   25

Definition at line 684 of file chan_dahdi.c.

◆ NUM_SPANS

#define NUM_SPANS   32

Definition at line 674 of file chan_dahdi.c.

◆ POLARITY_IDLE

#define POLARITY_IDLE   0

Definition at line 913 of file chan_dahdi.c.

◆ POLARITY_REV

#define POLARITY_REV   1

Definition at line 914 of file chan_dahdi.c.

◆ PROC_DAHDI_OPT_NOCHAN

#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)

process_dahdi() - ignore keyword 'channel' and similar

Definition at line 18420 of file chan_dahdi.c.

◆ PROC_DAHDI_OPT_NOWARN

#define PROC_DAHDI_OPT_NOWARN   (1 << 1)

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

Definition at line 18422 of file chan_dahdi.c.

◆ READ_SIZE

#define READ_SIZE   160

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

Definition at line 794 of file chan_dahdi.c.

◆ REPORT_CHANNEL_ALARMS

#define REPORT_CHANNEL_ALARMS   1

Definition at line 736 of file chan_dahdi.c.

◆ REPORT_SPAN_ALARMS

#define REPORT_SPAN_ALARMS   2

Definition at line 737 of file chan_dahdi.c.

◆ sig2str

#define sig2str   dahdi_sig2str

Definition at line 4703 of file chan_dahdi.c.

◆ SMDI_MD_WAIT_TIMEOUT

#define SMDI_MD_WAIT_TIMEOUT   1500 /* 1.5 seconds */

Definition at line 603 of file chan_dahdi.c.

◆ TRAILER_MS

#define TRAILER_MS   5

◆ TRANSFER

#define TRANSFER   0

Definition at line 16724 of file chan_dahdi.c.

Function Documentation

◆ __dahdi_exception()

static struct ast_frame * __dahdi_exception ( struct ast_channel ast)
static

Definition at line 8639 of file chan_dahdi.c.

8640{
8641 int res;
8642 int idx;
8643 struct ast_frame *f;
8644 int usedindex = -1;
8645 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8646
8647 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
8648 idx = SUB_REAL;
8649 }
8650
8651 p->subs[idx].f.frametype = AST_FRAME_NULL;
8652 p->subs[idx].f.datalen = 0;
8653 p->subs[idx].f.samples = 0;
8654 p->subs[idx].f.mallocd = 0;
8655 p->subs[idx].f.offset = 0;
8656 p->subs[idx].f.subclass.integer = 0;
8657 p->subs[idx].f.delivery = ast_tv(0,0);
8658 p->subs[idx].f.src = "dahdi_exception";
8659 p->subs[idx].f.data.ptr = NULL;
8660
8661
8662 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
8663 /* If nobody owns us, absorb the event appropriately, otherwise
8664 we loop indefinitely. This occurs when, during call waiting, the
8665 other end hangs up our channel so that it no longer exists, but we
8666 have neither FLASH'd nor ONHOOK'd to signify our desire to
8667 change to the other channel. */
8668 if (p->fake_event) {
8669 res = p->fake_event;
8670 p->fake_event = 0;
8671 } else
8672 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
8673 /* Switch to real if there is one and this isn't something really silly... */
8674 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
8675 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
8676 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
8677 p->owner = p->subs[SUB_REAL].owner;
8678 if (p->owner) {
8680 }
8681 p->subs[SUB_REAL].needunhold = 1;
8682 }
8683 switch (res) {
8684 case DAHDI_EVENT_ONHOOK:
8686 if (p->owner) {
8687 ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
8689 p->callwaitingrepeat = 0;
8690 p->cidcwexpire = 0;
8691 p->cid_suppress_expire = 0;
8692 } else
8693 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8695 break;
8696 case DAHDI_EVENT_RINGOFFHOOK:
8697 dahdi_ec_enable(p);
8698 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
8699 if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
8700 p->subs[SUB_REAL].needanswer = 1;
8701 p->dialing = 0;
8702 }
8703 break;
8704 case DAHDI_EVENT_HOOKCOMPLETE:
8705 case DAHDI_EVENT_RINGERON:
8706 case DAHDI_EVENT_RINGEROFF:
8707 /* Do nothing */
8708 break;
8709 case DAHDI_EVENT_WINKFLASH:
8710 p->flashtime = ast_tvnow();
8711 if (p->owner) {
8712 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
8714 /* Answer if necessary */
8715 usedindex = dahdi_get_index(p->owner, p, 0);
8716 if (usedindex > -1) {
8717 p->subs[usedindex].needanswer = 1;
8718 }
8720 }
8721 p->callwaitingrepeat = 0;
8722 p->cidcwexpire = 0;
8723 p->cid_suppress_expire = 0;
8725 p->subs[SUB_REAL].needunhold = 1;
8726 } else
8727 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8729 break;
8730 default:
8731 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
8732 }
8733 f = &p->subs[idx].f;
8734 return f;
8735 }
8736 if (!(p->radio || (p->oprmode < 0)))
8737 ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
8738 /* If it's not us, return NULL immediately */
8739 if (ast != p->owner) {
8740 if (p->owner) {
8741 ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
8742 }
8743 f = &p->subs[idx].f;
8744 return f;
8745 }
8746
8747 f = dahdi_handle_event(ast);
8748 if (!f) {
8749 const char *name = ast_strdupa(ast_channel_name(ast));
8750
8751 /* Tell the CDR this DAHDI device hung up */
8753 ast_channel_unlock(ast);
8754 ast_set_hangupsource(ast, name, 0);
8755 ast_channel_lock(ast);
8756 ast_mutex_lock(&p->lock);
8757 }
8758 return f;
8759}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
static int dahdi_ring_phone(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7452
char * name
Definition: chan_dahdi.c:4609
static int dahdi_set_hook(int fd, int hs)
Definition: chan_dahdi.c:5170
void dahdi_ec_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4886
void dahdi_conf_update(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4831
static struct ast_frame * dahdi_handle_event(struct ast_channel *ast)
Definition: chan_dahdi.c:7737
static const char * event2str(int event)
Definition: chan_dahdi.c:4630
void dahdi_ec_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4958
static int dahdi_get_event(int fd)
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition: chan_dahdi.c:773
#define SUB_REAL
Definition: chan_dahdi.h:57
#define dahdi_get_index(ast, p, nullok)
Definition: chan_dahdi.h:882
const char * ast_channel_name(const struct ast_channel *chan)
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2922
int ast_channel_fd(const struct ast_channel *chan, int which)
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it's bridge.
Definition: channel.c:2499
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1216
#define ast_channel_unlock(chan)
Definition: channel.h:2923
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_RINGING
Definition: channelstate.h:41
@ AST_STATE_UP
Definition: channelstate.h:42
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7386
@ AST_FRAME_NULL
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#define LOG_WARNING
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
#define NULL
Definition: resample.c:96
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@226 data
struct timeval delivery
enum ast_frame_type frametype
const char * src
int cid_suppress_expire
Definition: chan_dahdi.h:595
struct timeval flashtime
Definition: chan_dahdi.h:692
int oprmode
Definition: chan_dahdi.h:151
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
struct ast_channel * owner
Definition: chan_dahdi.h:127
int fake_event
Holding place for event injected from outside normal operation.
Definition: chan_dahdi.h:722
int radio
Nonzero if the signaling type is sent over a radio.
Definition: chan_dahdi.h:148
int cidcwexpire
Definition: chan_dahdi.h:594
int callwaitingrepeat
Definition: chan_dahdi.h:593
ast_mutex_t lock
Definition: chan_dahdi.h:125
int channel
Definition: chan_dahdi.h:585
unsigned int dialing
TRUE if in the process of dialing digits or sending something.
Definition: chan_dahdi.h:258
unsigned int needanswer
Definition: chan_dahdi.h:86
unsigned int needunhold
Definition: chan_dahdi.h:89
struct ast_frame f
Definition: chan_dahdi.h:82
struct ast_channel * owner
Definition: chan_dahdi.h:79
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235

References ast_channel_fd(), ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_unlock, ast_debug, AST_FRAME_NULL, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_queue_unhold(), ast_set_hangupsource(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_strdupa, ast_tv(), ast_tvnow(), ast_verb, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_conf_update(), dahdi_ec_disable(), dahdi_ec_enable(), 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, dahdi_pvt::flashtime, ast_frame::frametype, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_WARNING, ast_frame::mallocd, name, dahdi_subchannel::needanswer, dahdi_subchannel::needunhold, NULL, 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, and dahdi_pvt::subs.

Referenced by dahdi_exception(), and dahdi_read().

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 20521 of file chan_dahdi.c.

◆ __unload_module()

static int __unload_module ( void  )
static

Definition at line 18096 of file chan_dahdi.c.

18097{
18098 struct dahdi_pvt *p;
18099#if defined(HAVE_PRI) || defined(HAVE_SS7)
18100 int i, j;
18101#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18102
18103#ifdef HAVE_PRI
18104 for (i = 0; i < NUM_SPANS; i++) {
18105 if (pris[i].pri.master != AST_PTHREADT_NULL) {
18106 pthread_cancel(pris[i].pri.master);
18107 pthread_kill(pris[i].pri.master, SIGURG);
18108 }
18109 }
18110 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18111 ast_unregister_application(dahdi_send_keypad_facility_app);
18112#ifdef HAVE_PRI_PROG_W_CAUSE
18113 ast_unregister_application(dahdi_send_callrerouting_facility_app);
18114#endif
18115#endif
18116#if defined(HAVE_SS7)
18117 for (i = 0; i < NUM_SPANS; i++) {
18118 if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
18119 pthread_cancel(linksets[i].ss7.master);
18120 pthread_kill(linksets[i].ss7.master, SIGURG);
18121 }
18122 }
18123 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18124#endif /* defined(HAVE_SS7) */
18125#if defined(HAVE_OPENR2)
18126 dahdi_r2_destroy_links();
18127 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18128 ast_unregister_application(dahdi_accept_r2_call_app);
18129#endif
18130
18132
18134 ast_manager_unregister("DAHDIDialOffhook");
18135 ast_manager_unregister("DAHDIHangup");
18136 ast_manager_unregister("DAHDITransfer");
18137 ast_manager_unregister("DAHDIDNDoff");
18138 ast_manager_unregister("DAHDIDNDon");
18139 ast_manager_unregister("DAHDIShowChannels");
18140 ast_manager_unregister("DAHDIShowStatus");
18141 ast_manager_unregister("DAHDIRestart");
18142#if defined(HAVE_PRI)
18143 ast_manager_unregister("PRIShowSpans");
18144 ast_manager_unregister("PRIDebugSet");
18145 ast_manager_unregister("PRIDebugFileSet");
18146 ast_manager_unregister("PRIDebugFileUnset");
18147#endif /* defined(HAVE_PRI) */
18149
18150 /* Hangup all interfaces if they have an owner */
18152 for (p = iflist; p; p = p->next) {
18153 if (p->owner)
18155 }
18157
18160 pthread_cancel(monitor_thread);
18161 pthread_kill(monitor_thread, SIGURG);
18162 pthread_join(monitor_thread, NULL);
18163 }
18166
18168
18169#if defined(HAVE_PRI)
18170 for (i = 0; i < NUM_SPANS; i++) {
18171 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
18172 pthread_join(pris[i].pri.master, NULL);
18173 }
18174 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
18175 dahdi_close_pri_fd(&(pris[i]), j);
18176 }
18177 sig_pri_stop_pri(&pris[i].pri);
18178 }
18179#if defined(HAVE_PRI_CCSS)
18180 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
18181 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
18182#endif /* defined(HAVE_PRI_CCSS) */
18184#endif
18185
18186#if defined(HAVE_SS7)
18187 for (i = 0; i < NUM_SPANS; i++) {
18188 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
18189 pthread_join(linksets[i].ss7.master, NULL);
18190 }
18191 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
18192 dahdi_close_ss7_fd(&(linksets[i]), j);
18193 }
18194 if (linksets[i].ss7.ss7) {
18195 ss7_destroy(linksets[i].ss7.ss7);
18196 linksets[i].ss7.ss7 = NULL;
18197 }
18198 }
18199#endif /* defined(HAVE_SS7) */
18201
18203
18206 STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
18207 return 0;
18208}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
void dahdi_native_unload(void)
void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
Unregister a set of monitor callbacks with the core.
Definition: ccss.c:1195
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition: ccss.c:1232
static ast_mutex_t iflock
Protect the interface list (of dahdi_pvt's)
Definition: chan_dahdi.c:746
#define NUM_SPANS
Definition: chan_dahdi.c:674
static struct dahdi_pvt * iflist
Definition: chan_dahdi.c:922
static ast_cond_t ss_thread_complete
Definition: chan_dahdi.c:762
static ast_mutex_t monlock
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing some...
Definition: chan_dahdi.c:757
static struct ast_channel_tech dahdi_tech
Definition: chan_dahdi.c:1157
static struct ast_custom_function polarity_function
Definition: chan_dahdi.c:2903
static struct ast_cli_entry dahdi_cli[]
Definition: chan_dahdi.c:16709
static pthread_t monitor_thread
This is the thread for the monitor which checks for input on the channels which are not currently in ...
Definition: chan_dahdi.c:761
static void destroy_all_channels(void)
Definition: chan_dahdi.c:5913
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2471
@ AST_SOFTHANGUP_APPUNLOAD
Definition: channel.h:1143
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:8041
#define ast_cond_destroy(cond)
Definition: lock.h:202
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define AST_PTHREADT_STOP
Definition: lock.h:67
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
void sig_pri_unload(void)
#define SIG_PRI_NUM_DCHANS
Definition: sig_pri.h:239
void sig_pri_stop_pri(struct sig_pri_span *pri)
#define SIG_SS7_NUM_DCHANS
Definition: sig_ss7.h:56
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515
struct ast_format_cap * capabilities
Definition: channel.h:632
struct dahdi_pvt * next
Definition: chan_dahdi.h:169
#define ARRAY_LEN(a)
Definition: utils.h:666

References ao2_cleanup, ARRAY_LEN, ast_cc_agent_unregister(), ast_cc_monitor_unregister(), ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy, ast_custom_function_unregister(), 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, dahdi_cli, dahdi_native_unload(), dahdi_tech, destroy_all_channels(), iflist, iflock, sig_pri_span::master, sig_ss7_linkset::master, monitor_thread, monlock, dahdi_pvt::next, NULL, NUM_SPANS, dahdi_pvt::owner, polarity_function, SIG_PRI_NUM_DCHANS, sig_pri_stop_pri(), sig_pri_unload(), SIG_SS7_NUM_DCHANS, sig_ss7_linkset::ss7, ss_thread_complete, and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by load_module(), and unload_module().

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 20521 of file chan_dahdi.c.

◆ _dahdi_get_index()

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

Definition at line 3680 of file chan_dahdi.c.

3681{
3682 int res;
3683 if (p->subs[SUB_REAL].owner == ast)
3684 res = 0;
3685 else if (p->subs[SUB_CALLWAIT].owner == ast)
3686 res = 1;
3687 else if (p->subs[SUB_THREEWAY].owner == ast)
3688 res = 2;
3689 else {
3690 res = -1;
3691 if (!nullok)
3693 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
3694 ast ? ast_channel_name(ast) : "", p->channel, fname, line);
3695 }
3696 return res;
3697}
#define SUB_THREEWAY
Definition: chan_dahdi.h:59
#define SUB_CALLWAIT
Definition: chan_dahdi.h:58

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

◆ action_dahdidialoffhook()

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

Definition at line 16862 of file chan_dahdi.c.

16863{
16864 struct dahdi_pvt *p;
16865 const char *channel = astman_get_header(m, "DAHDIChannel");
16866 const char *number = astman_get_header(m, "Number");
16867 int i;
16868
16869 if (ast_strlen_zero(channel)) {
16870 astman_send_error(s, m, "No channel specified");
16871 return 0;
16872 }
16873 if (ast_strlen_zero(number)) {
16874 astman_send_error(s, m, "No number specified");
16875 return 0;
16876 }
16878 if (!p) {
16879 astman_send_error(s, m, "No such channel");
16880 return 0;
16881 }
16882 if (!p->owner) {
16883 astman_send_error(s, m, "Channel does not have it's owner");
16884 return 0;
16885 }
16886 for (i = 0; i < strlen(number); i++) {
16887 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16888 dahdi_queue_frame(p, &f);
16889 }
16890 astman_send_ack(s, m, "DAHDIDialOffhook");
16891 return 0;
16892}
static struct dahdi_pvt * find_channel_from_str(const char *channel)
Definition: chan_dahdi.c:16766
static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
Definition: chan_dahdi.c:3737
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3381
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3413
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3042
#define AST_FRAME_DTMF
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Number structure.
Definition: app_followme.c:154

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

Referenced by load_module().

◆ action_dahdidndoff()

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

Definition at line 16797 of file chan_dahdi.c.

16798{
16799 struct dahdi_pvt *p;
16800 const char *channel = astman_get_header(m, "DAHDIChannel");
16801
16802 if (ast_strlen_zero(channel)) {
16803 astman_send_error(s, m, "No channel specified");
16804 return 0;
16805 }
16807 if (!p) {
16808 astman_send_error(s, m, "No such channel");
16809 return 0;
16810 }
16811 dahdi_dnd(p, 0);
16812 astman_send_ack(s, m, "DND Disabled");
16813 return 0;
16814}
static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
Definition: chan_dahdi.c:9831

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

Referenced by load_module().

◆ action_dahdidndon()

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

Definition at line 16778 of file chan_dahdi.c.

16779{
16780 struct dahdi_pvt *p;
16781 const char *channel = astman_get_header(m, "DAHDIChannel");
16782
16783 if (ast_strlen_zero(channel)) {
16784 astman_send_error(s, m, "No channel specified");
16785 return 0;
16786 }
16788 if (!p) {
16789 astman_send_error(s, m, "No such channel");
16790 return 0;
16791 }
16792 dahdi_dnd(p, 1);
16793 astman_send_ack(s, m, "DND Enabled");
16794 return 0;
16795}

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

Referenced by load_module().

◆ action_dahdirestart()

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

Definition at line 15967 of file chan_dahdi.c.

15968{
15969 if (dahdi_restart() != 0) {
15970 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15971 return 1;
15972 }
15973 astman_send_ack(s, m, "DAHDIRestart: Success");
15974 return 0;
15975}
static int dahdi_restart(void)
Definition: chan_dahdi.c:15829

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

Referenced by load_module().

◆ action_dahdishowchannels()

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

Definition at line 16894 of file chan_dahdi.c.

16895{
16896 struct dahdi_pvt *tmp = NULL;
16897 const char *id = astman_get_header(m, "ActionID");
16898 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16899 char idText[256];
16900 int channels = 0;
16901 int dahdichanquery;
16902
16903 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16904 /* Not numeric string. */
16905 dahdichanquery = -1;
16906 }
16907
16908 idText[0] = '\0';
16909 if (!ast_strlen_zero(id)) {
16910 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16911 }
16912
16913 astman_send_listack(s, m, "DAHDI channel status will follow", "start");
16914
16916
16917 for (tmp = iflist; tmp; tmp = tmp->next) {
16918 if (tmp->channel > 0) {
16919 int alm;
16920
16921 /* If a specific channel is queried for, only deliver status for that channel */
16922 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16923 continue;
16924
16925 alm = get_alarms(tmp);
16926 channels++;
16927 if (tmp->owner) {
16928 /* Add data if we have a current call */
16929 astman_append(s,
16930 "Event: DAHDIShowChannels\r\n"
16931 "DAHDIChannel: %d\r\n"
16932 "Channel: %s\r\n"
16933 "Uniqueid: %s\r\n"
16934 "AccountCode: %s\r\n"
16935 "Signalling: %s\r\n"
16936 "SignallingCode: %d\r\n"
16937 "Context: %s\r\n"
16938 "DND: %s\r\n"
16939 "Alarm: %s\r\n"
16940 "Description: %s\r\n"
16941 "%s"
16942 "\r\n",
16943 tmp->channel,
16944 ast_channel_name(tmp->owner),
16945 ast_channel_uniqueid(tmp->owner),
16947 sig2str(tmp->sig),
16948 tmp->sig,
16949 tmp->context,
16950 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16951 alarm2str(alm),
16952 tmp->description, idText);
16953 } else {
16954 astman_append(s,
16955 "Event: DAHDIShowChannels\r\n"
16956 "DAHDIChannel: %d\r\n"
16957 "Signalling: %s\r\n"
16958 "SignallingCode: %d\r\n"
16959 "Context: %s\r\n"
16960 "DND: %s\r\n"
16961 "Alarm: %s\r\n"
16962 "Description: %s\r\n"
16963 "%s"
16964 "\r\n",
16965 tmp->channel, sig2str(tmp->sig), tmp->sig,
16966 tmp->context,
16967 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16968 alarm2str(alm),
16969 tmp->description, idText);
16970 }
16971 }
16972 }
16973
16975
16976 astman_send_list_complete_start(s, m, "DAHDIShowChannelsComplete", channels);
16977 astman_append(s, "Items: %d\r\n", channels);
16979 return 0;
16980}
static int tmp()
Definition: bt_open.c:389
static char * alarm2str(int alm)
Definition: chan_dahdi.c:4620
#define sig2str
Definition: chan_dahdi.c:4703
static int get_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7555
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char * ast_channel_accountcode(const struct ast_channel *chan)
static struct channel_usage channels
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3423
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3459
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3467
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3302

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_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), channels, dahdi_dnd(), get_alarms(), iflist, iflock, NULL, sig2str, and tmp().

Referenced by load_module().

◆ action_dahdishowstatus()

static int action_dahdishowstatus ( struct mansession s,
const struct message m 
)
static

Definition at line 16982 of file chan_dahdi.c.

16983{
16984 const char *id = astman_get_header(m, "ActionID");
16985 int span;
16986 int res;
16987 char alarmstr[50];
16988 int ctl;
16989 char idText[256];
16990 int numspans = 0;
16991 struct dahdi_spaninfo spaninfo;
16992
16993 ctl = open("/dev/dahdi/ctl", O_RDWR);
16994 if (ctl < 0) {
16995 astman_send_error(s, m, "No DAHDI detected");
16996 return 0;
16997 }
16998
16999 idText[0] = '\0';
17000 if (!ast_strlen_zero(id)) {
17001 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
17002 }
17003 astman_send_listack(s, m, "DAHDI span statuses will follow", "start");
17004
17005 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
17006 spaninfo.spanno = span;
17007 res = ioctl(ctl, DAHDI_SPANSTAT, &spaninfo);
17008 if (res) {
17009 continue;
17010 }
17011 numspans++;
17012 build_alarm_info(alarmstr, &spaninfo);
17013 astman_append(s,
17014 "Event: DAHDIShowStatus\r\n"
17015 "Span: %d\r\n"
17016 "Description: %s\r\n"
17017 "Alarms: %s\r\n"
17018 "IRQ: %d\r\n"
17019 "bpviol: %d\r\n"
17020 "CRC: %d\r\n"
17021 "Framing: %s\r\n"
17022 "Coding: %s\r\n"
17023 "Options: %s\r\n"
17024 "LBO: %s\r\n"
17025 "%s"
17026 "\r\n",
17027 span, spaninfo.desc, alarmstr, spaninfo.irqmisses, spaninfo.bpvcount, spaninfo.crc4count,
17028 spaninfo.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
17029 spaninfo.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
17030 spaninfo.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
17031 "CAS",
17032 spaninfo.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
17033 spaninfo.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
17034 spaninfo.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
17035 "Unk",
17036 spaninfo.lineconfig & DAHDI_CONFIG_CRC4 ?
17037 spaninfo.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
17038 spaninfo.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
17039 lbostr[spaninfo.lbo],
17040 idText);
17041 }
17042 close(ctl);
17043
17044 astman_send_list_complete_start(s, m, "DAHDIShowStatusComplete", numspans);
17045 astman_append(s, "Items: %d\r\n", numspans);
17047 return 0;
17048}
static void build_alarm_info(char *restrict alarmstr, struct dahdi_spaninfo *spaninfo)
Definition: chan_dahdi.c:16297
static const char *const lbostr[]
Definition: chan_dahdi.c:605

References ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), build_alarm_info(), lbostr, and dahdi_pvt::span.

Referenced by load_module().

◆ action_transfer()

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

Definition at line 16816 of file chan_dahdi.c.

16817{
16818 struct dahdi_pvt *p;
16819 const char *channel = astman_get_header(m, "DAHDIChannel");
16820
16821 if (ast_strlen_zero(channel)) {
16822 astman_send_error(s, m, "No channel specified");
16823 return 0;
16824 }
16826 if (!p) {
16827 astman_send_error(s, m, "No such channel");
16828 return 0;
16829 }
16830 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16831 astman_send_error(s, m, "Channel signaling is not analog");
16832 return 0;
16833 }
16835 astman_send_ack(s, m, "DAHDITransfer");
16836 return 0;
16837}
#define TRANSFER
Definition: chan_dahdi.c:16724
static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
Definition: chan_dahdi.c:16727
static int dahdi_analog_lib_handles(int signalling, int radio, int oprmode)
Definition: chan_dahdi.h:841

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

Referenced by load_module().

◆ action_transferhangup()

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

Definition at line 16839 of file chan_dahdi.c.

16840{
16841 struct dahdi_pvt *p;
16842 const char *channel = astman_get_header(m, "DAHDIChannel");
16843
16844 if (ast_strlen_zero(channel)) {
16845 astman_send_error(s, m, "No channel specified");
16846 return 0;
16847 }
16849 if (!p) {
16850 astman_send_error(s, m, "No such channel");
16851 return 0;
16852 }
16853 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16854 astman_send_error(s, m, "Channel signaling is not analog");
16855 return 0;
16856 }
16858 astman_send_ack(s, m, "DAHDIHangup");
16859 return 0;
16860}
#define HANGUP
Definition: chan_dahdi.c:16725

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

Referenced by load_module().

◆ alarm2str()

static char * alarm2str ( int  alm)
static

Definition at line 4620 of file chan_dahdi.c.

4621{
4622 int x;
4623 for (x = 0; x < ARRAY_LEN(alarms); x++) {
4624 if (alarms[x].alarm & alm)
4625 return alarms[x].name;
4626 }
4627 return alm ? "Unknown Alarm" : "No Alarm";
4628}
int alarm
Definition: chan_dahdi.c:4608
static struct @114 alarms[]

References alarm, alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), dahdi_show_channels(), and handle_alarms().

◆ alloc_sub()

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

Definition at line 4415 of file chan_dahdi.c.

4416{
4417 struct dahdi_bufferinfo bi;
4418 int res;
4419 if (p->subs[x].dfd >= 0) {
4420 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
4421 return -1;
4422 }
4423
4424 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
4425 if (p->subs[x].dfd <= -1) {
4426 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
4427 return -1;
4428 }
4429
4430 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
4431 if (!res) {
4432 bi.txbufpolicy = p->buf_policy;
4433 bi.rxbufpolicy = p->buf_policy;
4434 bi.numbufs = p->buf_no;
4435 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
4436 if (res < 0) {
4437 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
4438 }
4439 } else
4440 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
4441
4442 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
4443 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
4444 dahdi_close_sub(p, x);
4445 p->subs[x].dfd = -1;
4446 return -1;
4447 }
4448 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
4449 return 0;
4450}
static int dahdi_open(char *fn)
Definition: chan_dahdi.c:4334
static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
Definition: chan_dahdi.c:4387
const char *const subnames[]
Definition: chan_dahdi.c:916
int errno
int buf_policy
Definition: chan_dahdi.h:140
int buf_no
Definition: chan_dahdi.h:139

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, subnames, and dahdi_pvt::subs.

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

◆ analog_ss_thread()

static void * analog_ss_thread ( void *  data)
static

Definition at line 9877 of file chan_dahdi.c.

9878{
9879 struct ast_channel *chan = data;
9880 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9881 char exten[AST_MAX_EXTENSION] = "";
9882 char exten2[AST_MAX_EXTENSION] = "";
9883 unsigned char buf[256];
9884 char dtmfcid[300];
9885 char dtmfbuf[300];
9886 struct callerid_state *cs = NULL;
9887 char *name = NULL, *number = NULL;
9888 int distMatches;
9889 int curRingData[3];
9890 int receivedRingT;
9891 int counter1;
9892 int counter;
9893 int samples = 0;
9894 struct ast_smdi_md_message *smdi_msg = NULL;
9895 int flags = 0;
9896 int i;
9897 int timeout;
9898 int getforward = 0;
9899 char *s1, *s2;
9900 int len = 0;
9901 int res;
9902 int idx;
9903 RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
9904 const char *pickupexten;
9905
9909 /* in the bizarre case where the channel has become a zombie before we
9910 even get started here, abort safely
9911 */
9912 if (!p) {
9913 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
9914 ast_hangup(chan);
9915 goto quit;
9916 }
9917 ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
9918 idx = dahdi_get_index(chan, p, 1);
9919 if (idx < 0) {
9920 ast_log(LOG_WARNING, "Huh?\n");
9921 ast_hangup(chan);
9922 goto quit;
9923 }
9924
9925 ast_channel_lock(chan);
9926 pickup_cfg = ast_get_chan_features_pickup_config(chan);
9927 if (!pickup_cfg) {
9928 ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
9929 pickupexten = "";
9930 } else {
9931 pickupexten = ast_strdupa(pickup_cfg->pickupexten);
9932 }
9933 ast_channel_unlock(chan);
9934
9935 if (p->dsp)
9937 switch (p->sig) {
9938 case SIG_FEATD:
9939 case SIG_FEATDMF:
9940 case SIG_FEATDMF_TA:
9941 case SIG_E911:
9942 case SIG_FGC_CAMAMF:
9943 case SIG_FEATB:
9944 case SIG_EMWINK:
9945 case SIG_SF_FEATD:
9946 case SIG_SF_FEATDMF:
9947 case SIG_SF_FEATB:
9948 case SIG_SFWINK:
9949 if (dahdi_wink(p, idx))
9950 goto quit;
9951 /* Fall through */
9952 case SIG_EM:
9953 case SIG_EM_E1:
9954 case SIG_SF:
9955 case SIG_FGC_CAMA:
9956 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9957 if (p->dsp)
9959 /* set digit mode appropriately */
9960 if (p->dsp) {
9961 if (NEED_MFDETECT(p))
9963 else
9965 }
9966 memset(dtmfbuf, 0, sizeof(dtmfbuf));
9967 /* Wait for the first digit only if immediate=no */
9968 if (!p->immediate)
9969 /* Wait for the first digit (up to 5 seconds). */
9970 res = ast_waitfordigit(chan, 5000);
9971 else
9972 res = 0;
9973 if (res > 0) {
9974 /* save first char */
9975 dtmfbuf[0] = res;
9976 switch (p->sig) {
9977 case SIG_FEATD:
9978 case SIG_SF_FEATD:
9979 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
9980 if (res > 0)
9981 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
9982 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9983 break;
9984 case SIG_FEATDMF_TA:
9985 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9986 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9987 if (dahdi_wink(p, idx)) goto quit;
9988 dtmfbuf[0] = 0;
9989 /* Wait for the first digit (up to 5 seconds). */
9990 res = ast_waitfordigit(chan, 5000);
9991 if (res <= 0) break;
9992 dtmfbuf[0] = res;
9993 /* fall through intentionally */
9994 case SIG_FEATDMF:
9995 case SIG_E911:
9996 case SIG_FGC_CAMAMF:
9997 case SIG_SF_FEATDMF:
9998 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9999 /* if international caca, do it again to get real ANO */
10000 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10001 {
10002 if (dahdi_wink(p, idx)) goto quit;
10003 dtmfbuf[0] = 0;
10004 /* Wait for the first digit (up to 5 seconds). */
10005 res = ast_waitfordigit(chan, 5000);
10006 if (res <= 0) break;
10007 dtmfbuf[0] = res;
10008 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10009 }
10010 if (res > 0) {
10011 /* if E911, take off hook */
10012 if (p->sig == SIG_E911)
10013 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10014 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10015 }
10016 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10017 break;
10018 case SIG_FEATB:
10019 case SIG_SF_FEATB:
10020 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10021 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10022 break;
10023 case SIG_EMWINK:
10024 /* if we received a '*', we are actually receiving Feature Group D
10025 dial syntax, so use that mode; otherwise, fall through to normal
10026 mode
10027 */
10028 if (res == '*') {
10029 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10030 if (res > 0)
10031 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10032 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10033 break;
10034 }
10035 default:
10036 /* If we got the first digit, get the rest */
10037 len = 1;
10038 dtmfbuf[len] = '\0';
10039 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10040 if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10041 timeout = p->matchdigit_timeout;
10042 } else {
10043 timeout = p->interdigit_timeout;
10044 }
10045 res = ast_waitfordigit(chan, timeout);
10046 if (res < 0) {
10047 ast_debug(1, "waitfordigit returned < 0...\n");
10048 ast_hangup(chan);
10049 goto quit;
10050 } else if (res) {
10051 dtmfbuf[len++] = res;
10052 dtmfbuf[len] = '\0';
10053 } else {
10054 break;
10055 }
10056 }
10057 break;
10058 }
10059 }
10060 if (res == -1) {
10061 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10062 ast_hangup(chan);
10063 goto quit;
10064 } else if (res < 0) {
10065 ast_debug(1, "Got hung up before digits finished\n");
10066 ast_hangup(chan);
10067 goto quit;
10068 }
10069
10070 if (p->sig == SIG_FGC_CAMA) {
10071 char anibuf[100];
10072
10073 if (ast_safe_sleep(chan,1000) == -1) {
10074 ast_hangup(chan);
10075 goto quit;
10076 }
10077 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10079 res = my_getsigstr(chan, anibuf, "#", 10000);
10080 if ((res > 0) && (strlen(anibuf) > 2)) {
10081 if (anibuf[strlen(anibuf) - 1] == '#')
10082 anibuf[strlen(anibuf) - 1] = 0;
10083 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10084 }
10086 }
10087
10088 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10089 if (ast_strlen_zero(exten))
10090 ast_copy_string(exten, "s", sizeof(exten));
10091 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10092 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10093 if (exten[0] == '*') {
10094 char *stringp=NULL;
10095 ast_copy_string(exten2, exten, sizeof(exten2));
10096 /* Parse out extension and callerid */
10097 stringp=exten2 +1;
10098 s1 = strsep(&stringp, "*");
10099 s2 = strsep(&stringp, "*");
10100 if (s2) {
10101 if (!ast_strlen_zero(p->cid_num))
10102 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10103 else
10104 ast_set_callerid(chan, s1, NULL, s1);
10105 ast_copy_string(exten, s2, sizeof(exten));
10106 } else
10107 ast_copy_string(exten, s1, sizeof(exten));
10108 } else if (p->sig == SIG_FEATD)
10109 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10110 }
10111 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10112 if (exten[0] == '*') {
10113 char *stringp=NULL;
10114 ast_copy_string(exten2, exten, sizeof(exten2));
10115 /* Parse out extension and callerid */
10116 stringp=exten2 +1;
10117 s1 = strsep(&stringp, "#");
10118 s2 = strsep(&stringp, "#");
10119 if (s2) {
10120 if (!ast_strlen_zero(p->cid_num))
10121 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10122 else
10123 if (*(s1 + 2))
10124 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10125 ast_copy_string(exten, s2 + 1, sizeof(exten));
10126 } else
10127 ast_copy_string(exten, s1 + 2, sizeof(exten));
10128 } else
10129 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10130 }
10131 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10132 if (exten[0] == '*') {
10133 char *stringp=NULL;
10134 ast_copy_string(exten2, exten, sizeof(exten2));
10135 /* Parse out extension and callerid */
10136 stringp=exten2 +1;
10137 s1 = strsep(&stringp, "#");
10138 s2 = strsep(&stringp, "#");
10139 if (s2 && (*(s2 + 1) == '0')) {
10140 if (*(s2 + 2))
10141 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10142 }
10143 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10144 else ast_copy_string(exten, "911", sizeof(exten));
10145 } else
10146 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10147 }
10148 if (p->sig == SIG_FEATB) {
10149 if (exten[0] == '*') {
10150 char *stringp=NULL;
10151 ast_copy_string(exten2, exten, sizeof(exten2));
10152 /* Parse out extension and callerid */
10153 stringp=exten2 +1;
10154 s1 = strsep(&stringp, "#");
10155 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10156 } else
10157 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10158 }
10159 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10160 dahdi_wink(p, idx);
10161 /* some switches require a minimum guard time between
10162 the last FGD wink and something that answers
10163 immediately. This ensures it */
10164 if (ast_safe_sleep(chan, 100)) {
10165 ast_hangup(chan);
10166 goto quit;
10167 }
10168 }
10169 dahdi_ec_enable(p);
10170 if (NEED_MFDETECT(p)) {
10171 if (p->dsp) {
10172 if (!p->hardwaredtmf)
10174 else {
10175 ast_dsp_free(p->dsp);
10176 p->dsp = NULL;
10177 }
10178 }
10179 }
10180
10181 if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1,
10182 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
10183 ast_channel_exten_set(chan, exten);
10184 if (p->dsp) ast_dsp_digitreset(p->dsp);
10185 res = ast_pbx_run(chan);
10186 if (res) {
10187 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10188 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10189 }
10190 goto quit;
10191 } else {
10192 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, ast_channel_context(chan));
10193 sleep(2);
10194 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10195 if (res < 0)
10196 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10197 else
10198 sleep(1);
10199 res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
10200 if (res >= 0)
10201 ast_waitstream(chan, "");
10202 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10203 ast_hangup(chan);
10204 goto quit;
10205 }
10206 break;
10207 case SIG_FXOLS:
10208 case SIG_FXOGS:
10209 case SIG_FXOKS:
10210 /* Read the first digit */
10211 timeout = p->firstdigit_timeout;
10212 /* If starting a threeway call, never timeout on the first digit so someone
10213 can use flash-hook as a "hold" feature */
10214 if (p->subs[SUB_THREEWAY].owner)
10215 timeout = INT_MAX;
10216 while (len < AST_MAX_EXTENSION-1) {
10217 int is_exten_parking = 0;
10218
10219 /* Read digit unless it's supposed to be immediate, in which case the
10220 only answer is 's' */
10221 if (p->immediate)
10222 res = 's';
10223 else
10224 res = ast_waitfordigit(chan, timeout);
10225 timeout = 0;
10226 if (res < 0) {
10227 ast_debug(1, "waitfordigit returned < 0...\n");
10228 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10229 ast_hangup(chan);
10230 goto quit;
10231 } else if (res) {
10232 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10233 exten[len++]=res;
10234 exten[len] = '\0';
10235 }
10236 if (!ast_ignore_pattern(ast_channel_context(chan), exten)) {
10237 tone_zone_play_tone(p->subs[idx].dfd, -1);
10238 } else {
10239 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10240 }
10242 is_exten_parking = ast_parking_is_exten_park(ast_channel_context(chan), exten);
10243 }
10244 if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !is_exten_parking) {
10245 if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
10246 if (getforward) {
10247 /* Record this as the forwarding extension */
10248 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10249 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10250 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10251 if (res)
10252 break;
10253 usleep(500000);
10254 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10255 sleep(1);
10256 memset(exten, 0, sizeof(exten));
10257 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10258 len = 0;
10259 getforward = 0;
10260 } else {
10261 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10262 ast_channel_lock(chan);
10263 ast_channel_exten_set(chan, exten);
10264 if (!ast_strlen_zero(p->cid_num)) {
10265 if (!p->hidecallerid)
10266 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10267 else
10268 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10269 }
10270 if (!ast_strlen_zero(p->cid_name)) {
10271 if (!p->hidecallerid)
10272 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10273 }
10275 ast_channel_unlock(chan);
10276 dahdi_ec_enable(p);
10277 res = ast_pbx_run(chan);
10278 if (res) {
10279 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10280 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10281 }
10282 goto quit;
10283 }
10284 } else {
10285 /* It's a match, but they just typed a digit, and there is an ambiguous match,
10286 so just set the timeout to matchdigit_timeout and wait some more */
10287 timeout = p->matchdigit_timeout;
10288 }
10289 } else if (res == 0) {
10290 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10291 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10292 dahdi_wait_event(p->subs[idx].dfd);
10293 ast_hangup(chan);
10294 goto quit;
10295 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10296 ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
10297 /* Disable call waiting if enabled */
10298 p->callwaiting = 0;
10299 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10300 if (res) {
10301 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10302 ast_channel_name(chan), strerror(errno));
10303 }
10304 len = 0;
10305 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10306 memset(exten, 0, sizeof(exten));
10307 timeout = p->firstdigit_timeout;
10308
10309 } else if (!strcmp(exten, pickupexten)) {
10310 /* Scan all channels and see if there are any
10311 * ringing channels that have call groups
10312 * that equal this channels pickup group
10313 */
10314 if (idx == SUB_REAL) {
10315 /* Switch us from Third call to Call Wait */
10316 if (p->subs[SUB_THREEWAY].owner) {
10317 /* If you make a threeway call and the *8# a call, it should actually
10318 look like a callwait */
10322 }
10323 dahdi_ec_enable(p);
10324 if (ast_pickup_call(chan)) {
10325 ast_debug(1, "No call pickup possible...\n");
10326 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10327 dahdi_wait_event(p->subs[idx].dfd);
10328 }
10329 ast_hangup(chan);
10330 goto quit;
10331 } else {
10332 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10333 ast_hangup(chan);
10334 goto quit;
10335 }
10336
10337 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10338 ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
10339 /* Disable Caller*ID if enabled */
10340 p->hidecallerid = 1;
10345 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10346 if (res) {
10347 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10348 ast_channel_name(chan), strerror(errno));
10349 }
10350 len = 0;
10351 memset(exten, 0, sizeof(exten));
10352 timeout = p->firstdigit_timeout;
10353 } else if (p->callreturn && !strcmp(exten, "*69")) {
10354 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10355 break;
10356 } else if (!strcmp(exten, "*78")) {
10357 dahdi_dnd(p, 1);
10358 /* Do not disturb */
10359 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10360 getforward = 0;
10361 memset(exten, 0, sizeof(exten));
10362 len = 0;
10363 } else if (!strcmp(exten, "*79")) {
10364 dahdi_dnd(p, 0);
10365 /* Do not disturb */
10366 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10367 getforward = 0;
10368 memset(exten, 0, sizeof(exten));
10369 len = 0;
10370 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10371 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10372 getforward = 1;
10373 memset(exten, 0, sizeof(exten));
10374 len = 0;
10375 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10376 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10377 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10378 memset(p->call_forward, 0, sizeof(p->call_forward));
10379 getforward = 0;
10380 memset(exten, 0, sizeof(exten));
10381 len = 0;
10382 } else if ((p->transfer || p->canpark) && is_exten_parking
10383 && p->subs[SUB_THREEWAY].owner) {
10384 struct ast_bridge_channel *bridge_channel;
10385
10386 /*
10387 * This is a three way call, the main call being a real channel,
10388 * and we're parking the first call.
10389 */
10393 if (bridge_channel) {
10394 if (!ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten, NULL, NULL)) {
10395 /*
10396 * Swap things around between the three-way and real call so we
10397 * can hear where the channel got parked.
10398 */
10399 ast_mutex_lock(&p->lock);
10400 p->owner = p->subs[SUB_THREEWAY].owner;
10403
10404 ast_verb(3, "%s: Parked call\n", ast_channel_name(chan));
10406 ao2_ref(bridge_channel, -1);
10407 goto quit;
10408 }
10409 ao2_ref(bridge_channel, -1);
10410 }
10411 break;
10412 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10413 ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10414 /* Enable Caller*ID if enabled */
10415 p->hidecallerid = 0;
10417 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10418 if (res) {
10419 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10420 ast_channel_name(chan), strerror(errno));
10421 }
10422 len = 0;
10423 memset(exten, 0, sizeof(exten));
10424 timeout = p->firstdigit_timeout;
10425 } else if (!strcmp(exten, "*0")) {
10426 struct ast_channel *nbridge =
10428 struct dahdi_pvt *pbridge = NULL;
10429 RAII_VAR(struct ast_channel *, bridged, nbridge ? ast_channel_bridge_peer(nbridge) : NULL, ast_channel_cleanup);
10430
10431 /* set up the private struct of the bridged one, if any */
10432 if (nbridge && bridged) {
10433 pbridge = ast_channel_tech_pvt(bridged);
10434 }
10435 if (nbridge && pbridge &&
10436 (ast_channel_tech(nbridge) == &dahdi_tech) &&
10437 (ast_channel_tech(bridged) == &dahdi_tech) &&
10438 ISTRUNK(pbridge)) {
10439 int func = DAHDI_FLASH;
10440 /* Clear out the dial buffer */
10441 p->dop.dialstr[0] = '\0';
10442 /* flash hookswitch */
10443 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10444 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10445 ast_channel_name(nbridge), strerror(errno));
10446 }
10449 p->owner = p->subs[SUB_REAL].owner;
10451 ast_hangup(chan);
10452 goto quit;
10453 } else {
10454 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10455 dahdi_wait_event(p->subs[idx].dfd);
10456 tone_zone_play_tone(p->subs[idx].dfd, -1);
10459 p->owner = p->subs[SUB_REAL].owner;
10460 ast_hangup(chan);
10461 goto quit;
10462 }
10463 } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), exten, 1,
10464 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
10465 && !canmatch_featurecode(pickupexten, exten)) {
10466 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10467 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
10468 ast_channel_context(chan));
10469 break;
10470 }
10471 if (!timeout)
10472 timeout = p->interdigit_timeout;
10474 tone_zone_play_tone(p->subs[idx].dfd, -1);
10475 }
10476 break;
10477 case SIG_FXSLS:
10478 case SIG_FXSGS:
10479 case SIG_FXSKS:
10480 /* check for SMDI messages */
10481 if (p->use_smdi && p->smdi_iface) {
10483
10484 if (smdi_msg != NULL) {
10485 ast_channel_exten_set(chan, smdi_msg->fwd_st);
10486
10487 if (smdi_msg->type == 'B')
10488 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10489 else if (smdi_msg->type == 'N')
10490 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10491
10492 ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10493 } else {
10494 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10495 }
10496 }
10497
10498 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10499 number = smdi_msg->calling_st;
10500
10501 /* If we want caller id, we're in a prering state due to a polarity reversal
10502 * and we're set to use a polarity reversal to trigger the start of caller id,
10503 * grab the caller id and wait for ringing to start... */
10504 } else if (p->use_callerid && (ast_channel_state(chan) == AST_STATE_PRERING &&
10506 /* If set to use DTMF CID signalling, listen for DTMF */
10507 if (p->cid_signalling == CID_SIG_DTMF) {
10508 int k = 0;
10509 int off_ms;
10510 struct timeval start = ast_tvnow();
10511 int ms;
10512 cs = NULL;
10513 ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10514 dahdi_setlinear(p->subs[idx].dfd, 0);
10515 /*
10516 * We are the only party interested in the Rx stream since
10517 * we have not answered yet. We don't need or even want DTMF
10518 * emulation. The DTMF digits can come so fast that emulation
10519 * can drop some of them.
10520 */
10521 ast_channel_lock(chan);
10523 ast_channel_unlock(chan);
10524 off_ms = 4000;/* This is a typical OFF time between rings. */
10525 for (;;) {
10526 struct ast_frame *f;
10527
10528 ms = ast_remaining_ms(start, off_ms);
10529 res = ast_waitfor(chan, ms);
10530 if (res <= 0) {
10531 /*
10532 * We do not need to restore the dahdi_setlinear()
10533 * or AST_FLAG_END_DTMF_ONLY flag settings since we
10534 * are hanging up the channel.
10535 */
10536 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10537 "Exiting simple switch\n");
10538 ast_hangup(chan);
10539 goto quit;
10540 }
10541 f = ast_read(chan);
10542 if (!f)
10543 break;
10544 if (f->frametype == AST_FRAME_DTMF) {
10545 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10546 dtmfbuf[k++] = f->subclass.integer;
10547 }
10548 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10549 start = ast_tvnow();
10550 }
10551 ast_frfree(f);
10552 if (ast_channel_state(chan) == AST_STATE_RING ||
10554 break; /* Got ring */
10555 }
10556 ast_channel_lock(chan);
10558 ast_channel_unlock(chan);
10559 dtmfbuf[k] = '\0';
10560 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10561 /* Got cid and ring. */
10562 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10563 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10564 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10565 /* If first byte is NULL, we have no cid */
10566 if (!ast_strlen_zero(dtmfcid))
10567 number = dtmfcid;
10568 else
10569 number = NULL;
10570 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10571 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10573 if (cs) {
10574 int off_ms;
10575 struct timeval start;
10576 int ms;
10577 samples = 0;
10578#if 1
10579 bump_gains(p);
10580#endif
10581 /* Take out of linear mode for Caller*ID processing */
10582 dahdi_setlinear(p->subs[idx].dfd, 0);
10583
10584 /* First we wait and listen for the Caller*ID */
10585 for (;;) {
10586 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10587 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10588 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10589 callerid_free(cs);
10590 ast_hangup(chan);
10591 goto quit;
10592 }
10593 if (i & DAHDI_IOMUX_SIGEVENT) {
10594 res = dahdi_get_event(p->subs[idx].dfd);
10595 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10596 if (res == DAHDI_EVENT_NOALARM) {
10597 p->inalarm = 0;
10598 }
10599
10600 if (p->cid_signalling == CID_SIG_V23_JP) {
10601 if (res == DAHDI_EVENT_RINGBEGIN) {
10602 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10603 usleep(1);
10604 }
10605 } else {
10606 res = 0;
10607 break;
10608 }
10609 } else if (i & DAHDI_IOMUX_READ) {
10610 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10611 if (res < 0) {
10612 if (errno != ELAST) {
10613 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10614 callerid_free(cs);
10615 ast_hangup(chan);
10616 goto quit;
10617 }
10618 break;
10619 }
10620 samples += res;
10621
10622 if (p->cid_signalling == CID_SIG_V23_JP) {
10623 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10624 } else {
10625 res = callerid_feed(cs, buf, res, AST_LAW(p));
10626 }
10627 if (res < 0) {
10628 /*
10629 * The previous diagnostic message output likely
10630 * explains why it failed.
10631 */
10633 "Failed to decode CallerID on channel '%s'\n",
10634 ast_channel_name(chan));
10635 break;
10636 } else if (res)
10637 break;
10638 else if (samples > (8000 * 10))
10639 break;
10640 }
10641 }
10642 if (res == 1) {
10643 callerid_get(cs, &name, &number, &flags);
10644 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10645 }
10646
10647 if (p->cid_signalling == CID_SIG_V23_JP) {
10648 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10649 usleep(1);
10650 }
10651
10652 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10653 start = ast_tvnow();
10654 off_ms = 4000;/* This is a typical OFF time between rings. */
10655 for (;;) {
10656 struct ast_frame *f;
10657
10658 ms = ast_remaining_ms(start, off_ms);
10659 res = ast_waitfor(chan, ms);
10660 if (res <= 0) {
10661 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10662 "Exiting simple switch\n");
10663 ast_hangup(chan);
10664 goto quit;
10665 }
10666 if (!(f = ast_read(chan))) {
10667 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10668 ast_hangup(chan);
10669 goto quit;
10670 }
10671 ast_frfree(f);
10672 if (ast_channel_state(chan) == AST_STATE_RING ||
10674 break; /* Got ring */
10675 }
10676
10677 /* We must have a ring by now, so, if configured, lets try to listen for
10678 * distinctive ringing */
10680 len = 0;
10681 distMatches = 0;
10682 /* Clear the current ring data array so we don't have old data in it. */
10683 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10684 curRingData[receivedRingT] = 0;
10685 receivedRingT = 0;
10686 counter = 0;
10687 counter1 = 0;
10688 /* Check to see if context is what it should be, if not set to be. */
10689 if (strcmp(p->context,p->defcontext) != 0) {
10690 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10692 }
10693
10694 for (;;) {
10695 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10696 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10697 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10698 callerid_free(cs);
10699 ast_hangup(chan);
10700 goto quit;
10701 }
10702 if (i & DAHDI_IOMUX_SIGEVENT) {
10703 res = dahdi_get_event(p->subs[idx].dfd);
10704 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10705 if (res == DAHDI_EVENT_NOALARM) {
10706 p->inalarm = 0;
10707 }
10708 res = 0;
10709 /* Let us detect distinctive ring */
10710
10711 curRingData[receivedRingT] = p->ringt;
10712
10713 if (p->ringt < p->ringt_base/2)
10714 break;
10715 /* Increment the ringT counter so we can match it against
10716 values in chan_dahdi.conf for distinctive ring */
10717 if (++receivedRingT == ARRAY_LEN(curRingData))
10718 break;
10719 } else if (i & DAHDI_IOMUX_READ) {
10720 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10721 if (res < 0) {
10722 if (errno != ELAST) {
10723 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10724 callerid_free(cs);
10725 ast_hangup(chan);
10726 goto quit;
10727 }
10728 break;
10729 }
10730 if (p->ringt > 0) {
10731 if (!(--p->ringt)) {
10732 res = -1;
10733 break;
10734 }
10735 }
10736 }
10737 }
10738 /* this only shows up if you have n of the dring patterns filled in */
10739 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10740 for (counter = 0; counter < 3; counter++) {
10741 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10742 channel */
10743 distMatches = 0;
10744 for (counter1 = 0; counter1 < 3; counter1++) {
10745 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10746 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10747 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10748 curRingData[counter1]);
10749 distMatches++;
10750 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10751 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10752 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10753 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10754 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10755 distMatches++;
10756 }
10757 }
10758
10759 if (distMatches == 3) {
10760 /* The ring matches, set the context to whatever is for distinctive ring.. */
10761 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10763 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10764 break;
10765 }
10766 }
10767 }
10768 /* Restore linear mode (if appropriate) for Caller*ID processing */
10769 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10770#if 1
10771 restore_gains(p);
10772#endif
10773 } else
10774 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10775 } else {
10776 ast_log(LOG_WARNING, "Channel %s in prering "
10777 "state, but I have nothing to do. "
10778 "Terminating simple switch, should be "
10779 "restarted by the actual ring.\n",
10780 ast_channel_name(chan));
10781 ast_hangup(chan);
10782 goto quit;
10783 }
10784 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10785 if (p->cid_signalling == CID_SIG_DTMF) {
10786 int k = 0;
10787 int off_ms;
10788 struct timeval start;
10789 int ms;
10790 cs = NULL;
10791 dahdi_setlinear(p->subs[idx].dfd, 0);
10792 off_ms = 2000;
10793 start = ast_tvnow();
10794 for (;;) {
10795 struct ast_frame *f;
10796
10797 ms = ast_remaining_ms(start, off_ms);
10798 res = ast_waitfor(chan, ms);
10799 if (res <= 0) {
10800 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10801 "Exiting simple switch\n");
10802 ast_hangup(chan);
10803 goto quit;
10804 }
10805 f = ast_read(chan);
10806 if (!f) {
10807 /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10808 ast_hangup(chan);
10809 goto quit;
10810 }
10811 if (f->frametype == AST_FRAME_DTMF) {
10812 dtmfbuf[k++] = f->subclass.integer;
10813 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10814 start = ast_tvnow();
10815 }
10816 ast_frfree(f);
10817
10818 if (p->ringt_base == p->ringt)
10819 break;
10820 }
10821 dtmfbuf[k] = '\0';
10822 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10823 /* Got cid and ring. */
10824 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10825 ast_debug(1, "CID is '%s', flags %d\n",
10826 dtmfcid, flags);
10827 /* If first byte is NULL, we have no cid */
10828 if (!ast_strlen_zero(dtmfcid))
10829 number = dtmfcid;
10830 else
10831 number = NULL;
10832 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10833 } else {
10834 /* FSK Bell202 callerID */
10836 if (cs) {
10837#if 1
10838 bump_gains(p);
10839#endif
10840 samples = 0;
10841 len = 0;
10842 distMatches = 0;
10843 /* Clear the current ring data array so we don't have old data in it. */
10844 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10845 curRingData[receivedRingT] = 0;
10846 receivedRingT = 0;
10847 counter = 0;
10848 counter1 = 0;
10849 /* Check to see if context is what it should be, if not set to be. */
10850 if (strcmp(p->context,p->defcontext) != 0) {
10851 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10853 }
10854
10855 /* Take out of linear mode for Caller*ID processing */
10856 dahdi_setlinear(p->subs[idx].dfd, 0);
10857 for (;;) {
10858 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10859 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10860 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10861 callerid_free(cs);
10862 ast_hangup(chan);
10863 goto quit;
10864 }
10865 if (i & DAHDI_IOMUX_SIGEVENT) {
10866 res = dahdi_get_event(p->subs[idx].dfd);
10867 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10868 if (res == DAHDI_EVENT_NOALARM) {
10869 p->inalarm = 0;
10870 }
10871 /* If we get a PR event, they hung up while processing calerid */
10872 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10873 ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10875 callerid_free(cs);
10876 ast_hangup(chan);
10877 goto quit;
10878 }
10879 res = 0;
10880 /* Let us detect callerid when the telco uses distinctive ring */
10881
10882 curRingData[receivedRingT] = p->ringt;
10883
10884 if (p->ringt < p->ringt_base/2)
10885 break;
10886 /* Increment the ringT counter so we can match it against
10887 values in chan_dahdi.conf for distinctive ring */
10888 if (++receivedRingT == ARRAY_LEN(curRingData))
10889 break;
10890 } else if (i & DAHDI_IOMUX_READ) {
10891 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10892 if (res < 0) {
10893 if (errno != ELAST) {
10894 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10895 callerid_free(cs);
10896 ast_hangup(chan);
10897 goto quit;
10898 }
10899 break;
10900 }
10901 if (p->ringt > 0) {
10902 if (!(--p->ringt)) {
10903 res = -1;
10904 break;
10905 }
10906 }
10907 samples += res;
10908 res = callerid_feed(cs, buf, res, AST_LAW(p));
10909 if (res < 0) {
10910 /*
10911 * The previous diagnostic message output likely
10912 * explains why it failed.
10913 */
10915 "Failed to decode CallerID on channel '%s'\n",
10916 ast_channel_name(chan));
10917 break;
10918 } else if (res)
10919 break;
10920 else if (samples > (8000 * 10))
10921 break;
10922 }
10923 }
10924 if (res == 1) {
10925 callerid_get(cs, &name, &number, &flags);
10926 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10927 }
10928 if (distinctiveringaftercid == 1) {
10929 /* Clear the current ring data array so we don't have old data in it. */
10930 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10931 curRingData[receivedRingT] = 0;
10932 }
10933 receivedRingT = 0;
10934 ast_verb(3, "Detecting post-CID distinctive ring\n");
10935 for (;;) {
10936 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10937 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10938 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10939 callerid_free(cs);
10940 ast_hangup(chan);
10941 goto quit;
10942 }
10943 if (i & DAHDI_IOMUX_SIGEVENT) {
10944 res = dahdi_get_event(p->subs[idx].dfd);
10945 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10946 if (res == DAHDI_EVENT_NOALARM) {
10947 p->inalarm = 0;
10948 }
10949 res = 0;
10950 /* Let us detect callerid when the telco uses distinctive ring */
10951
10952 curRingData[receivedRingT] = p->ringt;
10953
10954 if (p->ringt < p->ringt_base/2)
10955 break;
10956 /* Increment the ringT counter so we can match it against
10957 values in chan_dahdi.conf for distinctive ring */
10958 if (++receivedRingT == ARRAY_LEN(curRingData))
10959 break;
10960 } else if (i & DAHDI_IOMUX_READ) {
10961 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10962 if (res < 0) {
10963 if (errno != ELAST) {
10964 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10965 callerid_free(cs);
10966 ast_hangup(chan);
10967 goto quit;
10968 }
10969 break;
10970 }
10971 if (p->ringt > 0) {
10972 if (!(--p->ringt)) {
10973 res = -1;
10974 break;
10975 }
10976 }
10977 }
10978 }
10979 }
10981 /* this only shows up if you have n of the dring patterns filled in */
10982 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10983
10984 for (counter = 0; counter < 3; counter++) {
10985 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10986 channel */
10987 /* this only shows up if you have n of the dring patterns filled in */
10988 ast_verb(3, "Checking %d,%d,%d\n",
10989 p->drings.ringnum[counter].ring[0],
10990 p->drings.ringnum[counter].ring[1],
10991 p->drings.ringnum[counter].ring[2]);
10992 distMatches = 0;
10993 for (counter1 = 0; counter1 < 3; counter1++) {
10994 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10995 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10996 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10997 curRingData[counter1]);
10998 distMatches++;
10999 }
11000 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11001 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11002 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11003 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11004 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11005 distMatches++;
11006 }
11007 }
11008 if (distMatches == 3) {
11009 /* The ring matches, set the context to whatever is for distinctive ring.. */
11010 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11012 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11013 break;
11014 }
11015 }
11016 }
11017 /* Restore linear mode (if appropriate) for Caller*ID processing */
11018 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11019#if 1
11020 restore_gains(p);
11021#endif
11022 if (res < 0) {
11023 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
11024 }
11025 } else
11026 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11027 }
11028 } else
11029 cs = NULL;
11030
11031 if (number)
11034
11035 ao2_cleanup(smdi_msg);
11036
11037 if (cs)
11038 callerid_free(cs);
11039
11040 my_handle_notify_message(chan, p, flags, -1);
11041
11042 ast_channel_lock(chan);
11044 ast_channel_rings_set(chan, 1);
11045 ast_channel_unlock(chan);
11046 p->ringt = p->ringt_base;
11047 res = ast_pbx_run(chan);
11048 if (res) {
11049 ast_hangup(chan);
11050 ast_log(LOG_WARNING, "PBX exited non-zero\n");
11051 }
11052 goto quit;
11053 default:
11054 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11055 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11056 if (res < 0)
11057 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11058 }
11059 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11060 if (res < 0)
11061 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11062 ast_hangup(chan);
11063quit:
11068 return NULL;
11069}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define CID_SIG_V23_JP
Definition: callerid.h:63
#define CID_SIG_SMDI
Definition: callerid.h:64
int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int samples, struct ast_format *codec)
Read samples into the state machine.
Definition: callerid.c:306
void callerid_free(struct callerid_state *cid)
This function frees callerid_state cid.
Definition: callerid.c:734
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s,...
Definition: callerid.c:1002
#define CID_SIG_DTMF
Definition: callerid.h:62
struct callerid_state * callerid_new(int cid_signalling)
Create a callerID state machine.
Definition: callerid.c:129
#define CID_SIG_V23
Definition: callerid.h:61
int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int samples, struct ast_format *codec)
Read samples into the state machine.
Definition: callerid.c:545
void callerid_get_dtmf(char *cidstring, char *number, int *flags)
Get and parse DTMF-based callerid.
Definition: callerid.c:201
#define CID_START_RING
Definition: callerid.h:66
#define CID_START_POLARITY
Definition: callerid.h:67
void callerid_get(struct callerid_state *cid, char **number, char **name, int *flags)
Extract info out of callerID state machine. Flags are listed above.
Definition: callerid.c:188
#define CID_START_POLARITY_IN
Definition: callerid.h:68
#define CID_START_DTMF_NOALERT
Definition: callerid.h:69
static ast_mutex_t ss_thread_lock
Definition: chan_dahdi.c:763
static int restore_gains(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5157
static int unalloc_sub(struct dahdi_pvt *p, int x)
Definition: chan_dahdi.c:4452
static int dahdi_wink(struct dahdi_pvt *p, int index)
Definition: chan_dahdi.c:9784
static int dahdi_wait_event(int fd)
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition: chan_dahdi.c:782
static int canmatch_featurecode(const char *pickupexten, const char *exten)
Definition: chan_dahdi.c:9850
static int distinctiveringaftercid
Definition: chan_dahdi.c:729
static int bump_gains(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5143
#define AST_LAW(p)
Definition: chan_dahdi.c:642
static int dahdi_setlinear(int dfd, int linear)
Definition: chan_dahdi.c:4409
static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
Definition: chan_dahdi.c:3556
static int alloc_sub(struct dahdi_pvt *p, int x)
Definition: chan_dahdi.c:4415
#define NEED_MFDETECT(p)
Signaling types that need to use MF detection should be placed in this macro.
Definition: chan_dahdi.c:646
static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
Definition: chan_dahdi.c:9765
#define SMDI_MD_WAIT_TIMEOUT
Definition: chan_dahdi.c:603
static void swap_subs(struct dahdi_pvt *p, int a, int b)
Definition: chan_dahdi.c:4306
#define ISTRUNK(p)
Definition: chan_dahdi.c:711
#define POLARITY_IDLE
Definition: chan_dahdi.c:913
#define POLARITY_REV
Definition: chan_dahdi.c:914
static int ss_thread_count
Definition: chan_dahdi.c:765
#define SIG_FEATB
Definition: chan_dahdi.h:781
#define SIG_FGC_CAMA
Definition: chan_dahdi.h:784
#define SIG_SFWINK
Definition: chan_dahdi.h:793
#define SIG_EMWINK
Definition: chan_dahdi.h:778
#define SIG_SF_FEATB
Definition: chan_dahdi.h:796
#define SIG_FXOGS
Definition: chan_dahdi.h:790
#define SIG_SF_FEATDMF
Definition: chan_dahdi.h:795
#define SIG_FXOKS
Definition: chan_dahdi.h:791
#define SIG_FGC_CAMAMF
Definition: chan_dahdi.h:785
#define SIG_FEATDMF
Definition: chan_dahdi.h:780
#define SIG_EM_E1
Definition: chan_dahdi.h:797
#define SIG_SF_FEATD
Definition: chan_dahdi.h:794
#define SIG_FEATD
Definition: chan_dahdi.h:779
#define SIG_FEATDMF_TA
Definition: chan_dahdi.h:783
#define SIG_FXOLS
Definition: chan_dahdi.h:789
#define SIG_E911
Definition: chan_dahdi.h:782
#define SIG_EM
Definition: chan_dahdi.h:777
#define SIG_SF
Definition: chan_dahdi.h:792
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3175
void ast_channel_rings_set(struct ast_channel *chan, int value)
void ast_party_name_init(struct ast_party_name *init)
Initialize the given name structure.
Definition: channel.c:1591
void ast_party_number_init(struct ast_party_number *init)
Initialize the given number structure.
Definition: channel.c:1644
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10564
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3162
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4257
void ast_party_name_free(struct ast_party_name *doomed)
Destroy the party name contents.
Definition: channel.c:1638
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7334
void ast_party_number_free(struct ast_party_number *doomed)
Destroy the party number contents.
Definition: channel.c:1691
const char * ast_channel_language(const struct ast_channel *chan)
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel's bridge pointer.
Definition: channel.c:10582
void ast_channel_context_set(struct ast_channel *chan, const char *value)
@ AST_FLAG_END_DTMF_ONLY
Definition: channel.h:1007
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2969
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1574
#define AST_MAX_EXTENSION
Definition: channel.h:134
@ AST_STATE_RING
Definition: channelstate.h:40
@ AST_STATE_PRERING
Definition: channelstate.h:45
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1783
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
Definition: dsp.c:1810
#define DSP_DIGITMODE_MF
Definition: dsp.h:32
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
Definition: dsp.c:1857
#define DSP_DIGITMODE_DTMF
Definition: dsp.h:31
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1293
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1840
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * strsep(char **str, const char *delims)
struct ast_features_pickup_config * ast_get_chan_features_pickup_config(struct ast_channel *chan)
Get the pickup configuration options for a channel.
#define ast_frfree(fr)
#define LOG_ERROR
#define LOG_NOTICE
#define ast_cond_signal(cond)
Definition: lock.h:203
int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker, const char *context, const char *exten, transfer_channel_cb parked_channel_cb, struct transfer_channel_data *parked_channel_data)
Perform a blind transfer to a parking extension.
Definition: parking.c:143
int ast_parking_is_exten_park(const char *context, const char *exten)
Determine if the context/exten is a "parking" extension.
Definition: parking.c:179
int ast_parking_provider_registered(void)
Check whether a parking provider is registered.
Definition: parking.c:241
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4755
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4175
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:4190
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:6879
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch)
Definition: pbx.c:4195
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition: pickup.c:199
struct ast_smdi_md_message * ast_smdi_md_message_wait(struct ast_smdi_interface *iface, int timeout)
Get the next SMDI message from the queue.
Definition: res_smdi.c:539
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Structure that contains information regarding a channel in a bridge.
struct ast_channel * chan
Main Channel structure associated with a channel.
const char * data
Configuration relating to call pickup.
unsigned int flags
An SMDI message desk message.
Definition: smdi.h:65
char calling_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:70
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:69
struct ringContextData ringContext[3]
Definition: chan_dahdi.h:71
struct distRingData ringnum[3]
Definition: chan_dahdi.h:70
unsigned int immediate
TRUE if the channel should be answered immediately without attempting to gather any digits.
Definition: chan_dahdi.h:316
struct dahdi_distRings drings
Distinctive Ring data.
Definition: chan_dahdi.h:485
unsigned int canpark
TRUE if support for call parking is enabled.
Definition: chan_dahdi.h:243
struct dahdi_dialoperation dop
DAHDI dial operation command struct for ioctl() call.
Definition: chan_dahdi.h:696
char cid_num[AST_MAX_EXTENSION]
Caller ID number from an incoming call.
Definition: chan_dahdi.h:526
int ringt
Ring timeout timer??
Definition: chan_dahdi.h:603
int interdigit_timeout
Time (ms) to detect following digits (in an analog phone)
Definition: chan_dahdi.h:685
unsigned int usedistinctiveringdetection
TRUE if distinctive rings are to be detected.
Definition: chan_dahdi.h:403
int dtmfrelax
Definition: chan_dahdi.h:720
unsigned int callwaiting
TRUE if busy extensions will hear the call-waiting tone and can use hook-flash to switch between call...
Definition: chan_dahdi.h:226
char exten[AST_MAX_EXTENSION]
Extension to use in the dialplan.
Definition: chan_dahdi.h:502
unsigned int hanguponpolarityswitch
TRUE if the call will be considered "hung up" on a polarity reversal.
Definition: chan_dahdi.h:285
char call_forward[AST_MAX_EXTENSION]
Accumulated call forwarding number.
Definition: chan_dahdi.h:704
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
Definition: chan_dahdi.h:302
unsigned int callreturn
TRUE if call return is enabled. (*69, if your dialplan doesn't catch this first)
Definition: chan_dahdi.h:219
unsigned int use_smdi
TRUE if SMDI (Simplified Message Desk Interface) is enabled.
Definition: chan_dahdi.h:479
int ringt_base
Ring timeout base.
Definition: chan_dahdi.h:608
int cid_start
Definition: chan_dahdi.h:589
char defcontext[AST_MAX_CONTEXT]
Default distinctive ring context.
Definition: chan_dahdi.h:500
struct ast_dsp * dsp
Opaque DSP configuration structure.
Definition: chan_dahdi.h:694
char context[AST_MAX_CONTEXT]
The configured context for incoming calls.
Definition: chan_dahdi.h:491
unsigned int cancallforward
TRUE if support for call forwarding enabled. Dial *72 to enable call forwarding. Dial *73 to disable ...
Definition: chan_dahdi.h:238
unsigned int hardwaredtmf
TRUE if DTMF detection needs to be done by hardware.
Definition: chan_dahdi.h:295
int firstdigit_timeout
Time (ms) to detect first digit (in an analog phone)
Definition: chan_dahdi.h:680
int cid_signalling
Definition: chan_dahdi.h:588
unsigned int transfer
TRUE if call transfer is enabled.
Definition: chan_dahdi.h:382
unsigned int inalarm
TRUE if in an alarm condition.
Definition: chan_dahdi.h:324
char cid_name[AST_MAX_EXTENSION]
Caller ID name from an incoming call.
Definition: chan_dahdi.h:535
int matchdigit_timeout
Time (ms) to wait, in case of ambiguous match (in an analog phone)
Definition: chan_dahdi.h:690
unsigned int use_callerid
TRUE if caller ID is used on this channel.
Definition: chan_dahdi.h:390
int polarity
Current line interface polarity. POLARITY_IDLE, POLARITY_REV.
Definition: chan_dahdi.h:736
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
Definition: chan_dahdi.h:482
unsigned int linear
Definition: chan_dahdi.h:90
int ring[3]
Definition: chan_dahdi.h:63
char contextData[AST_MAX_CONTEXT]
Definition: chan_dahdi.h:67
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:2281
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define ast_set_flag(p, flag)
Definition: utils.h:70

References alloc_sub(), ao2_cleanup, ao2_ref, ARRAY_LEN, ast_canmatch_extension(), ast_channel_bridge_peer(), ast_channel_caller(), ast_channel_cleanup, ast_channel_context(), ast_channel_context_set(), ast_channel_exten_set(), ast_channel_flags(), ast_channel_get_bridge_channel(), ast_channel_language(), ast_channel_lock, ast_channel_name(), ast_channel_rings_set(), ast_channel_tech(), ast_channel_tech_pvt(), ast_channel_unlock, ast_clear_flag, ast_cond_signal, ast_copy_string(), ast_debug, ast_dsp_digitreset(), ast_dsp_free(), ast_dsp_set_digitmode(), ast_exists_extension(), AST_FLAG_END_DTMF_ONLY, AST_FRAME_DTMF, ast_frfree, ast_get_chan_features_pickup_config(), ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log, ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_parking_blind_transfer_park(), ast_parking_is_exten_park(), ast_parking_provider_registered(), ast_party_name_free(), ast_party_name_init(), ast_party_number_free(), ast_party_number_init(), ast_pbx_run(), ast_pickup_call(), ast_queue_unhold(), ast_read(), ast_remaining_ms(), ast_safe_sleep(), ast_set_callerid(), ast_set_flag, ast_setstate(), ast_shrink_phone_number(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_tvnow(), ast_verb, ast_waitfor(), ast_waitfordigit(), ast_waitstream(), buf, bump_gains(), dahdi_pvt::call_forward, 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, ast_bridge_channel::chan, 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, ringContextData::contextData, dahdi_dnd(), dahdi_ec_enable(), dahdi_get_event(), dahdi_get_index, dahdi_set_hook(), dahdi_setlinear(), dahdi_tech, dahdi_wait_event(), dahdi_wink(), ast_channel::data, dahdi_pvt::defcontext, dahdi_subchannel::dfd, distinctiveringaftercid, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), dahdi_pvt::exten, dahdi_pvt::firstdigit_timeout, ast_frame::flags, ast_frame::frametype, ast_smdi_md_message::fwd_st, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_pvt::interdigit_timeout, ISTRUNK, len(), dahdi_subchannel::linear, dahdi_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::matchdigit_timeout, my_getsigstr(), my_handle_notify_message(), name, NEED_MFDETECT, NULL, dahdi_subchannel::owner, dahdi_pvt::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, RAII_VAR, distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_COR, S_OR, ast_frame::samples, 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_complete, ss_thread_count, ss_thread_lock, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), dahdi_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), dahdi_pvt::use_callerid, dahdi_pvt::use_smdi, and dahdi_pvt::usedistinctiveringdetection.

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

◆ analog_tone_to_dahditone()

static int analog_tone_to_dahditone ( enum analog_tone  tone)
static

Definition at line 1233 of file chan_dahdi.c.

1234{
1235 switch (tone) {
1237 return DAHDI_TONE_RINGTONE;
1239 return DAHDI_TONE_STUTTER;
1241 return DAHDI_TONE_CONGESTION;
1243 return DAHDI_TONE_DIALTONE;
1245 return DAHDI_TONE_DIALRECALL;
1246 case ANALOG_TONE_INFO:
1247 return DAHDI_TONE_INFO;
1248 default:
1249 return -1;
1250 }
1251}
@ ANALOG_TONE_CONGESTION
Definition: sig_analog.h:73
@ ANALOG_TONE_INFO
Definition: sig_analog.h:76
@ ANALOG_TONE_DIALTONE
Definition: sig_analog.h:74
@ ANALOG_TONE_DIALRECALL
Definition: sig_analog.h:75
@ ANALOG_TONE_STUTTER
Definition: sig_analog.h:72
@ ANALOG_TONE_RINGTONE
Definition: sig_analog.h:71

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

◆ analogsub_to_dahdisub()

static int analogsub_to_dahdisub ( enum analog_sub  analogsub)
static

Definition at line 1253 of file chan_dahdi.c.

1254{
1255 int index;
1256
1257 switch (analogsub) {
1258 case ANALOG_SUB_REAL:
1259 index = SUB_REAL;
1260 break;
1262 index = SUB_CALLWAIT;
1263 break;
1265 index = SUB_THREEWAY;
1266 break;
1267 default:
1268 ast_log(LOG_ERROR, "Unidentified sub!\n");
1269 index = SUB_REAL;
1270 }
1271
1272 return index;
1273}
@ ANALOG_SUB_THREEWAY
Definition: sig_analog.h:111
@ ANALOG_SUB_REAL
Definition: sig_analog.h:109
@ ANALOG_SUB_CALLWAIT
Definition: sig_analog.h:110

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

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 20521 of file chan_dahdi.c.

◆ attempt_transfer()

static int attempt_transfer ( struct dahdi_pvt p)
static

Definition at line 7496 of file chan_dahdi.c.

7497{
7498 struct ast_channel *owner_real;
7499 struct ast_channel *owner_3way;
7500 enum ast_transfer_result xfer_res;
7501 int res = 0;
7502
7503 owner_real = ast_channel_ref(p->subs[SUB_REAL].owner);
7504 owner_3way = ast_channel_ref(p->subs[SUB_THREEWAY].owner);
7505
7506 ast_verb(3, "TRANSFERRING %s to %s\n",
7507 ast_channel_name(owner_3way), ast_channel_name(owner_real));
7508
7509 ast_channel_unlock(owner_real);
7510 ast_channel_unlock(owner_3way);
7512
7513 xfer_res = ast_bridge_transfer_attended(owner_3way, owner_real);
7514 if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
7516 res = -1;
7517 }
7518
7519 /* Must leave with these locked. */
7520 ast_channel_lock(owner_real);
7521 ast_mutex_lock(&p->lock);
7522
7523 ast_channel_unref(owner_real);
7524 ast_channel_unref(owner_3way);
7525
7526 return res;
7527}
ast_transfer_result
Definition: bridge.h:1098
@ AST_BRIDGE_TRANSFER_SUCCESS
Definition: bridge.h:1100
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
Definition: bridge.c:4677
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1121

References ast_bridge_transfer_attended(), AST_BRIDGE_TRANSFER_SUCCESS, ast_channel_lock, ast_channel_name(), ast_channel_ref, ast_channel_unlock, ast_channel_unref, ast_mutex_lock, ast_mutex_unlock, ast_softhangup(), AST_SOFTHANGUP_DEV, ast_verb, dahdi_pvt::lock, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.

Referenced by dahdi_handle_event().

◆ available()

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

Definition at line 13460 of file chan_dahdi.c.

13461{
13462 struct dahdi_pvt *p = *pvt;
13463
13464 if (p->inalarm)
13465 return 0;
13466
13467 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode))
13468 return analog_available(p->sig_pvt);
13469
13470 switch (p->sig) {
13471#if defined(HAVE_PRI)
13473 {
13474 struct sig_pri_chan *pvt_chan;
13475 int res;
13476
13477 pvt_chan = p->sig_pvt;
13478 res = sig_pri_available(&pvt_chan, is_specific_channel);
13479 *pvt = pvt_chan->chan_pvt;
13480 return res;
13481 }
13482#endif /* defined(HAVE_PRI) */
13483#if defined(HAVE_SS7)
13484 case SIG_SS7:
13485 return sig_ss7_available(p->sig_pvt);
13486#endif /* defined(HAVE_SS7) */
13487 default:
13488 break;
13489 }
13490
13491 if (p->locallyblocked || p->remotelyblocked) {
13492 return 0;
13493 }
13494
13495 /* If no owner definitely available */
13496 if (!p->owner) {
13497#ifdef HAVE_OPENR2
13498 /* Trust MFC/R2 */
13499 if (p->mfcr2) {
13500 if (p->mfcr2call) {
13501 return 0;
13502 } else {
13503 return 1;
13504 }
13505 }
13506#endif
13507 return 1;
13508 }
13509
13510 return 0;
13511}
#define SIG_PRI_LIB_HANDLE_CASES
Definition: chan_dahdi.h:811
#define SIG_SS7
Definition: chan_dahdi.h:805
int analog_available(struct analog_pvt *p)
Definition: sig_analog.c:793
int sig_pri_available(struct sig_pri_chan **pvt, int is_specific_channel)
int sig_ss7_available(struct sig_ss7_chan *p)
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: chan_dahdi.h:451
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked. 1 maintenance, 2 blocked in hardware.
Definition: chan_dahdi.h:460
void * sig_pvt
Definition: chan_dahdi.h:764
void * chan_pvt
Definition: sig_pri.h:374

References analog_available(), sig_pri_chan::chan_pvt, dahdi_analog_lib_handles(), 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(), dahdi_request(), is_member_available(), logger_register_level(), sip_options_contact_status_available_count(), and sip_options_update_aor_task().

◆ build_alarm_info()

static void build_alarm_info ( char *restrict  alarmstr,
struct dahdi_spaninfo *  spaninfo 
)
static

Definition at line 16297 of file chan_dahdi.c.

16298{
16299 alarmstr[0] = '\0';
16300 if (spaninfo->alarms > 0) {
16301 if (spaninfo->alarms & DAHDI_ALARM_BLUE) {
16302 strcat(alarmstr, "BLU/");
16303 }
16304 if (spaninfo->alarms & DAHDI_ALARM_YELLOW) {
16305 strcat(alarmstr, "YEL/");
16306 }
16307 if (spaninfo->alarms & DAHDI_ALARM_RED) {
16308 strcat(alarmstr, "RED/");
16309 }
16310 if (spaninfo->alarms & DAHDI_ALARM_LOOPBACK) {
16311 strcat(alarmstr, "LB/");
16312 }
16313 if (spaninfo->alarms & DAHDI_ALARM_RECOVER) {
16314 strcat(alarmstr, "REC/");
16315 }
16316 if (spaninfo->alarms & DAHDI_ALARM_NOTOPEN) {
16317 strcat(alarmstr, "NOP/");
16318 }
16319 if (!strlen(alarmstr)) {
16320 strcat(alarmstr, "UUU/");
16321 }
16322 if (strlen(alarmstr)) {
16323 /* Strip trailing / */
16324 alarmstr[strlen(alarmstr) - 1] = '\0';
16325 }
16326 } else {
16327 if (spaninfo->numchans) {
16328 strcpy(alarmstr, "OK");
16329 } else {
16330 strcpy(alarmstr, "UNCONFIGURED");
16331 }
16332 }
16333}

Referenced by action_dahdishowstatus(), and dahdi_show_status().

◆ build_channels()

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

Definition at line 18226 of file chan_dahdi.c.

18227{
18228 char *c, *chan;
18229 int x, start, finish;
18230 struct dahdi_pvt *tmp;
18231
18232 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
18233 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
18234 return -1;
18235 }
18236
18237 c = ast_strdupa(value);
18238
18239 while ((chan = strsep(&c, ","))) {
18240 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
18241 /* Range */
18242 } else if (sscanf(chan, "%30d", &start)) {
18243 /* Just one */
18244 finish = start;
18245 } else if (!strcasecmp(chan, "pseudo")) {
18246 finish = start = CHAN_PSEUDO;
18247 } else {
18248 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
18249 return -1;
18250 }
18251 if (finish < start) {
18252 ast_log(LOG_WARNING, "Silliness: %d < %d\n", start, finish);
18253 x = finish;
18254 finish = start;
18255 start = x;
18256 }
18257
18258 for (x = start; x <= finish; x++) {
18259 if (conf->wanted_channels_start &&
18260 (x < conf->wanted_channels_start ||
18261 x > conf->wanted_channels_end)
18262 ) {
18263 continue;
18264 }
18265 tmp = mkintf(x, conf, reload);
18266
18267 if (tmp) {
18268 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
18269 } else {
18270 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
18271 (reload == 1) ? "reconfigure" : "register", value);
18272 return -1;
18273 }
18274 if (x == CHAN_PSEUDO) {
18275 has_pseudo = 1;
18276 }
18277 }
18278 }
18279
18280 return 0;
18281}
static struct dahdi_pvt * mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
Definition: chan_dahdi.c:12481
static int has_pseudo
Definition: chan_dahdi.c:688
static int reload(void)
Definition: chan_dahdi.c:20497
#define CHAN_PSEUDO
Definition: chan_dahdi.c:677
All configuration options for http media cache.
int value
Definition: syslog.c:37
static struct test_val c

References ast_log, ast_strdupa, ast_verb, c, CHAN_PSEUDO, has_pseudo, LOG_ERROR, LOG_WARNING, mkintf(), reload(), sig2str, strsep(), tmp(), and value.

Referenced by process_dahdi().

◆ bump_gains()

static int bump_gains ( struct dahdi_pvt p)
static

Definition at line 5143 of file chan_dahdi.c.

5144{
5145 int res;
5146
5147 /* Bump receive gain by value stored in cid_rxgain */
5148 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5149 if (res) {
5150 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
5151 return -1;
5152 }
5153
5154 return 0;
5155}
static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
Definition: chan_dahdi.c:5138
float cid_rxgain
Amount of gain to increase during caller id.
Definition: chan_dahdi.h:158
float txdrc
Definition: chan_dahdi.h:164
int law
Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
Definition: chan_dahdi.h:556
float rxdrc
Definition: chan_dahdi.h:165
float txgain
Software Tx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:162
float rxgain
Software Rx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:160

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

◆ calc_energy()

static int calc_energy ( const unsigned char *  buf,
int  len,
struct ast_format law 
)
static

Definition at line 11077 of file chan_dahdi.c.

11078{
11079 int x;
11080 int sum = 0;
11081
11082 if (!len)
11083 return 0;
11084
11085 for (x = 0; x < len; x++)
11086 sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11087
11088 return sum / len;
11089}
#define AST_ALAW(a)
Definition: alaw.h:84
#define abs(x)
Definition: f2c.h:195
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
#define AST_MULAW(a)
Definition: ulaw.h:85

References abs, AST_ALAW, ast_format_ulaw, AST_MULAW, buf, dahdi_pvt::law, and len().

Referenced by do_monitor(), and mwi_thread().

◆ canmatch_featurecode()

static int canmatch_featurecode ( const char *  pickupexten,
const char *  exten 
)
static

Definition at line 9850 of file chan_dahdi.c.

9851{
9852 int extlen = strlen(exten);
9853
9854 if (!extlen) {
9855 return 1;
9856 }
9857
9858 if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
9859 return 1;
9860 }
9861 /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
9862 if (exten[0] == '*' && extlen < 3) {
9863 if (extlen == 1) {
9864 return 1;
9865 }
9866 /* "*0" should be processed before it gets here */
9867 switch (exten[1]) {
9868 case '6':
9869 case '7':
9870 case '8':
9871 return 1;
9872 }
9873 }
9874 return 0;
9875}

Referenced by analog_ss_thread().

◆ check_for_conference()

static int check_for_conference ( struct dahdi_pvt p)
static

Definition at line 7529 of file chan_dahdi.c.

7530{
7531 struct dahdi_confinfo ci;
7532 /* Fine if we already have a master, etc */
7533 if (p->master || (p->confno > -1))
7534 return 0;
7535 memset(&ci, 0, sizeof(ci));
7536 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
7537 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
7538 return 0;
7539 }
7540 /* If we have no master and don't have a confno, then
7541 if we're in a conference, it's probably a MeetMe room or
7542 some such, so don't let us 3-way out! */
7543 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
7544 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
7545 return 1;
7546 }
7547 return 0;
7548}
struct dahdi_pvt * master
Definition: chan_dahdi.h:135
int confno
Definition: chan_dahdi.h:557
struct dahdi_confinfo curconf
Definition: chan_dahdi.h:92

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

◆ conf_add()

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

Definition at line 4705 of file chan_dahdi.c.

4706{
4707 /* If the conference already exists, and we're already in it
4708 don't bother doing anything */
4709 struct dahdi_confinfo zi;
4710
4711 memset(&zi, 0, sizeof(zi));
4712 zi.chan = 0;
4713
4714 if (slavechannel > 0) {
4715 /* If we have only one slave, do a digital mon */
4716 zi.confmode = DAHDI_CONF_DIGITALMON;
4717 zi.confno = slavechannel;
4718 } else {
4719 if (!idx) {
4720 /* Real-side and pseudo-side both participate in conference */
4721 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
4722 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
4723 } else
4724 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
4725 zi.confno = p->confno;
4726 }
4727 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
4728 return 0;
4729 if (c->dfd < 0)
4730 return 0;
4731 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4732 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
4733 return -1;
4734 }
4735 if (slavechannel < 1) {
4736 p->confno = zi.confno;
4737 }
4738 c->curconf = zi;
4739 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4740 return 0;
4741}

References ast_debug, ast_log, c, dahdi_pvt::confno, errno, and LOG_WARNING.

Referenced by dahdi_conf_update(), my_complete_conference_update(), and my_conf_add().

◆ conf_del()

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

Definition at line 4754 of file chan_dahdi.c.

4755{
4756 struct dahdi_confinfo zi;
4757 if (/* Can't delete if there's no dfd */
4758 (c->dfd < 0) ||
4759 /* Don't delete from the conference if it's not our conference */
4760 !isourconf(p, c)
4761 /* Don't delete if we don't think it's conferenced at all (implied) */
4762 ) return 0;
4763 memset(&zi, 0, sizeof(zi));
4764 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4765 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
4766 return -1;
4767 }
4768 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4769 memcpy(&c->curconf, &zi, sizeof(c->curconf));
4770 return 0;
4771}
static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
Definition: chan_dahdi.c:4743

References ast_debug, ast_log, c, errno, isourconf(), and LOG_WARNING.

Referenced by dahdi_conf_update(), dahdi_master_slave_unlink(), and my_conf_del().

◆ create_channel_name()

static struct ast_str * create_channel_name ( struct dahdi_pvt i)
static

Definition at line 9464 of file chan_dahdi.c.

9466{
9467 struct ast_str *chan_name;
9468 int x, y;
9469
9470 /* Create the new channel name tail. */
9471 if (!(chan_name = ast_str_create(32))) {
9472 return NULL;
9473 }
9474 if (i->channel == CHAN_PSEUDO) {
9475 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
9476#if defined(HAVE_PRI)
9477 } else if (i->pri) {
9478 ast_mutex_lock(&i->pri->lock);
9479 y = ++i->pri->new_chan_seq;
9480 if (is_outgoing) {
9481 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
9482 address[0] = '\0';
9483 } else if (ast_strlen_zero(i->cid_subaddr)) {
9484 /* Put in caller-id number only since there is no subaddress. */
9485 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
9486 } else {
9487 /* Put in caller-id number and subaddress. */
9488 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
9489 i->cid_subaddr, (unsigned)y);
9490 }
9491 ast_mutex_unlock(&i->pri->lock);
9492#endif /* defined(HAVE_PRI) */
9493 } else {
9494 y = 1;
9495 do {
9496 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
9497 for (x = 0; x < 3; ++x) {
9498 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
9499 ast_channel_name(i->subs[x].owner) + 6)) {
9500 break;
9501 }
9502 }
9503 ++y;
9504 } while (x < 3);
9505 }
9506 return chan_name;
9507}
char * address
Definition: f2c.h:59
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
Support for dynamic strings.
Definition: strings.h:623
char cid_subaddr[AST_MAX_EXTENSION]
Caller ID subaddress from an incoming call.
Definition: chan_dahdi.h:537
long int ast_random(void)
Definition: utils.c:2312

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, NULL, dahdi_subchannel::owner, dahdi_pvt::span, and dahdi_pvt::subs.

Referenced by dahdi_cc_callback(), and dahdi_new().

◆ dahdi_ami_channel_event()

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

Definition at line 1956 of file chan_dahdi.c.

1957{
1958 char ch_name[23];
1959
1960 if (p->channel < CHAN_PSEUDO) {
1961 /* No B channel */
1962 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
1963 } else if (p->channel == CHAN_PSEUDO) {
1964 /* Pseudo channel */
1965 strcpy(ch_name, "pseudo");
1966 } else {
1967 /* Real channel */
1968 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
1969 }
1970 publish_dahdichannel(chan, p->group, p->span, ch_name);
1971}
static void publish_dahdichannel(struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages.
Definition: chan_dahdi.c:1929
ast_group_t group
Bitmapped groups this belongs to.
Definition: chan_dahdi.h:552

References CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::group, publish_dahdichannel(), and dahdi_pvt::span.

Referenced by dahdi_new().

◆ dahdi_answer()

static int dahdi_answer ( struct ast_channel ast)
static
Todo:
XXX this is redundantly set by the analog and PRI submodules!

Definition at line 6687 of file chan_dahdi.c.

6688{
6689 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6690 int res = 0;
6691 int idx;
6692 ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
6693 ast_mutex_lock(&p->lock);
6694 idx = dahdi_get_index(ast, p, 0);
6695 if (idx < 0)
6696 idx = SUB_REAL;
6697 /* nothing to do if a radio channel */
6698 if ((p->radio || (p->oprmode < 0))) {
6700 return 0;
6701 }
6702
6703 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
6704 res = analog_answer(p->sig_pvt, ast);
6706 return res;
6707 }
6708
6709 switch (p->sig) {
6710#if defined(HAVE_PRI)
6712 res = sig_pri_answer(p->sig_pvt, ast);
6713 break;
6714#endif /* defined(HAVE_PRI) */
6715#if defined(HAVE_SS7)
6716 case SIG_SS7:
6717 res = sig_ss7_answer(p->sig_pvt, ast);
6718 break;
6719#endif /* defined(HAVE_SS7) */
6720#ifdef HAVE_OPENR2
6721 case SIG_MFCR2:
6722 if (!p->mfcr2_call_accepted) {
6723 /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
6724 openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
6725 p->mfcr2_answer_pending = 1;
6726 if (p->mfcr2_charge_calls) {
6727 ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
6728 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
6729 } else {
6730 ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
6731 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
6732 }
6733 } else {
6734 ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
6735 dahdi_r2_answer(p);
6736 }
6737 break;
6738#endif
6739 case 0:
6741 return 0;
6742 default:
6743 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
6744 res = -1;
6745 break;
6746 }
6748 return res;
6749}
#define SIG_MFCR2
Definition: chan_dahdi.h:808
int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:1490
int sig_pri_answer(struct sig_pri_chan *p, struct ast_channel *ast)
int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)

References analog_answer(), ast_channel_tech_pvt(), ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_UP, dahdi_pvt::channel, dahdi_analog_lib_handles(), 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(), and SUB_REAL.

◆ dahdi_call()

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

Definition at line 5381 of file chan_dahdi.c.

5382{
5383 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5384 int x, res, mysig;
5385 char *dest;
5387 AST_APP_ARG(group); /* channel/group token */
5388 AST_APP_ARG(ext); /* extension token */
5389 //AST_APP_ARG(opts); /* options token */
5390 AST_APP_ARG(other); /* Any remining unused arguments */
5391 );
5392
5393 ast_mutex_lock(&p->lock);
5394 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
5395
5396 /* Split the dialstring */
5397 dest = ast_strdupa(rdest);
5398 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
5399 if (!args.ext) {
5400 args.ext = "";
5401 }
5402
5403#if defined(HAVE_PRI)
5405 char *subaddr;
5406
5407 sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
5408
5409 /* Remove any subaddress for uniformity with incoming calls. */
5410 subaddr = strchr(p->exten, ':');
5411 if (subaddr) {
5412 *subaddr = '\0';
5413 }
5414 } else
5415#endif /* defined(HAVE_PRI) */
5416 {
5417 ast_copy_string(p->exten, args.ext, sizeof(p->exten));
5418 }
5419
5420 if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
5421 p->subs[SUB_REAL].needbusy = 1;
5423 return 0;
5424 }
5426 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
5428 return -1;
5429 }
5430 p->waitingfordt.tv_sec = 0;
5431 p->dialednone = 0;
5432 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
5433 {
5434 /* Special pseudo -- automatically up */
5437 return 0;
5438 }
5439 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
5440 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
5441 if (res)
5442 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
5443 p->outgoing = 1;
5444
5446 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
5447 } else {
5448 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5449 }
5450
5451#ifdef HAVE_PRI
5453 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
5454 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
5456 return res;
5457 }
5458#endif
5459
5460#if defined(HAVE_SS7)
5461 if (p->sig == SIG_SS7) {
5462 res = sig_ss7_call(p->sig_pvt, ast, rdest);
5464 return res;
5465 }
5466#endif /* defined(HAVE_SS7) */
5467
5468 /* If this is analog signalling we can exit here */
5469 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
5470 p->callwaitrings = 0;
5471 res = analog_call(p->sig_pvt, ast, rdest, timeout);
5473 return res;
5474 }
5475
5476 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
5477 switch (mysig) {
5478 case 0:
5479 /* Special pseudo -- automatically up*/
5481 break;
5482 case SIG_MFCR2:
5483 break;
5484 default:
5485 ast_debug(1, "not yet implemented\n");
5487 return -1;
5488 }
5489
5490#ifdef HAVE_OPENR2
5491 if (p->mfcr2) {
5492 openr2_calling_party_category_t chancat;
5493 int callres = 0;
5494 char *c, *l;
5495
5496 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
5497 p->dialdest[0] = '\0';
5498
5499 c = args.ext;
5500 if (!p->hidecallerid) {
5502 } else {
5503 l = NULL;
5504 }
5505 if (strlen(c) < p->stripmsd) {
5506 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
5508 return -1;
5509 }
5510 p->dialing = 1;
5511 chancat = dahdi_r2_get_channel_category(ast);
5512 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
5513 if (-1 == callres) {
5515 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
5516 return -1;
5517 }
5518 p->mfcr2_call_accepted = 0;
5519 p->mfcr2_progress_sent = 0;
5521 }
5522#endif /* HAVE_OPENR2 */
5524 return 0;
5525}
static int dahdi_sig_pri_lib_handles(int signaling)
Definition: chan_dahdi.h:825
unsigned short ast_channel_transfercapability(const struct ast_channel *chan)
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
@ AST_STATE_DOWN
Definition: channelstate.h:36
@ AST_STATE_BUSY
Definition: channelstate.h:43
@ AST_STATE_DIALING
Definition: channelstate.h:39
@ AST_STATE_RESERVED
Definition: channelstate.h:37
const char * ext
Definition: http.c:150
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
int analog_call(struct analog_pvt *p, struct ast_channel *ast, const char *rdest, int timeout)
Definition: sig_analog.c:990
void sig_pri_extract_called_num_subaddr(struct sig_pri_chan *p, const char *rdest, char *called, size_t called_buff_size)
int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rdest, int timeout, int layer1)
int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, const char *rdest)
struct ast_party_id id
Connected party ID.
Definition: channel.h:458
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:342
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:297
char * str
Subscriber phone number (Malloced)
Definition: channel.h:291
char dialdest[256]
Delayed dialing for E911. Overlap digits for ISDN.
Definition: chan_dahdi.h:713
unsigned int outgoing
TRUE if we originated the call leg.
Definition: chan_dahdi.h:328
int outsigmod
Definition: chan_dahdi.h:150
int callwaitrings
Number of call waiting rings.
Definition: chan_dahdi.h:624
unsigned int dialednone
TRUE if analog type line dialed no digits in Dial()
Definition: chan_dahdi.h:253
struct timeval waitingfordt
Definition: chan_dahdi.h:691
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
Definition: chan_dahdi.h:615
unsigned int needbusy
Definition: chan_dahdi.h:84
const char * args
#define IS_DIGITAL(cap)
Definition: transcap.h:45

References analog_call(), args, AST_APP_ARG, ast_channel_connected(), ast_channel_name(), ast_channel_tech_pvt(), ast_channel_transfercapability(), 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, c, dahdi_pvt::callwaitrings, dahdi_pvt::channel, dahdi_analog_lib_handles(), 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, NULL, 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, dahdi_pvt::txdrc, dahdi_pvt::txgain, ast_party_number::valid, and dahdi_pvt::waitingfordt.

◆ dahdi_callwait()

static int dahdi_callwait ( struct ast_channel ast)
static

Definition at line 5347 of file chan_dahdi.c.

5348{
5349 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5350
5352 if (p->cidspill) {
5353 ast_log(LOG_WARNING, "Spill already exists?!?\n");
5354 ast_free(p->cidspill);
5355 }
5356
5357 /*
5358 * SAS: Subscriber Alert Signal, 440Hz for 300ms
5359 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
5360 */
5361 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
5362 return -1;
5363 save_conference(p);
5364 /* Silence */
5365 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
5366 if (!p->callwaitrings && p->callwaitingcallerid) {
5367 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
5368 p->callwaitcas = 1;
5369 p->cidlen = 2400 + 680 + READ_SIZE * 4;
5370 } else {
5371 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
5372 p->callwaitcas = 0;
5373 p->cidlen = 2400 + READ_SIZE * 4;
5374 }
5375 p->cidpos = 0;
5376 send_callerid(p);
5377
5378 return 0;
5379}
#define ast_free(a)
Definition: astmm.h:180
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
int ast_gen_cas(unsigned char *outbuf, int sas, int len, struct ast_format *codec)
Generate a CAS (CPE Alert Signal) tone for 'n' samples.
Definition: callerid.c:261
#define CALLWAITING_REPEAT_SAMPLES
Definition: chan_dahdi.c:800
static int save_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5224
#define READ_SIZE
Definition: chan_dahdi.c:794
static int send_callerid(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5311
unsigned char * cidspill
Analog caller ID waveform sample buffer.
Definition: chan_dahdi.h:597
int cidlen
Length of the cidspill buffer containing samples.
Definition: chan_dahdi.h:601
unsigned int callwaitingcallerid
TRUE if send caller ID for Call Waiting.
Definition: chan_dahdi.h:231
int callwaitcas
TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
Definition: chan_dahdi.h:622
int cidpos
Position in the cidspill buffer to send out next.
Definition: chan_dahdi.h:599

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

Referenced by dahdi_read().

◆ dahdi_cc_callback()

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
inboundIncoming asterisk channel.
destSame dial string passed to dahdi_request().
callbackCallback 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
0on success.
-1on error.

Definition at line 14134 of file chan_dahdi.c.

14135{
14136 struct dahdi_pvt *p;
14137 struct dahdi_pvt *exitpvt;
14138 struct dahdi_starting_point start;
14139 int groupmatched = 0;
14140 int channelmatched = 0;
14141
14143 p = determine_starting_point(dest, &start);
14144 if (!p) {
14146 return -1;
14147 }
14148 exitpvt = p;
14149 for (;;) {
14150 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
14151 /* We found a potential match. call the callback */
14152 struct ast_str *device_name;
14153 char *dash;
14154 const char *monitor_type;
14155 char dialstring[AST_CHANNEL_NAME];
14156 char full_device_name[AST_CHANNEL_NAME];
14157
14160 break;
14164#if defined(HAVE_PRI)
14166 /*
14167 * ISDN is in a trunk busy condition so we need to monitor
14168 * the span congestion device state.
14169 */
14170 snprintf(full_device_name, sizeof(full_device_name),
14171 "DAHDI/I%d/congestion", p->pri->span);
14172 } else
14173#endif /* defined(HAVE_PRI) */
14174 {
14175#if defined(HAVE_PRI)
14176 device_name = create_channel_name(p, 1, "");
14177#else
14178 device_name = create_channel_name(p);
14179#endif /* defined(HAVE_PRI) */
14180 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14181 device_name ? ast_str_buffer(device_name) : "");
14182 ast_free(device_name);
14183 /*
14184 * The portion after the '-' in the channel name is either a random
14185 * number, a sequence number, or a subchannel number. None are
14186 * necessary so strip them off.
14187 */
14188 dash = strrchr(full_device_name, '-');
14189 if (dash) {
14190 *dash = '\0';
14191 }
14192 }
14193 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14194
14195 /*
14196 * Analog can only do generic monitoring.
14197 * ISDN is in a trunk busy condition and any "device" is going
14198 * to be busy until a B channel becomes available. The generic
14199 * monitor can do this task.
14200 */
14201 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14202 callback(inbound,
14203#if defined(HAVE_PRI)
14204 p->pri ? p->pri->cc_params : p->cc_params,
14205#else
14206 p->cc_params,
14207#endif /* defined(HAVE_PRI) */
14208 monitor_type, full_device_name, dialstring, NULL);
14209 break;
14210 }
14211 }
14212 p = start.backwards ? p->prev : p->next;
14213 if (!p) {
14214 p = start.backwards ? ifend : iflist;
14215 }
14216 if (p == exitpvt) {
14217 break;
14218 }
14219 }
14221 return 0;
14222}
#define AST_CC_GENERIC_MONITOR_TYPE
Definition: ccss.h:455
@ AST_CC_MONITOR_NEVER
Definition: ccss.h:76
@ AST_CC_MONITOR_ALWAYS
Definition: ccss.h:87
@ AST_CC_MONITOR_NATIVE
Definition: ccss.h:78
@ AST_CC_MONITOR_GENERIC
Definition: ccss.h:83
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
Definition: ccss.c:876
static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
Definition: chan_dahdi.c:13427
static struct ast_str * create_channel_name(struct dahdi_pvt *i)
Definition: chan_dahdi.c:9464
static struct dahdi_pvt * ifend
Definition: chan_dahdi.c:923
static struct dahdi_pvt * determine_starting_point(const char *data, struct dahdi_starting_point *param)
Definition: chan_dahdi.c:13730
#define AST_CHANNEL_NAME
Definition: channel.h:171
struct dahdi_pvt * prev
Definition: chan_dahdi.h:170
struct ast_cc_config_params * cc_params
Definition: chan_dahdi.h:765

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

◆ dahdi_chan_conf_default()

static struct dahdi_chan_conf dahdi_chan_conf_default ( void  )
static

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

Definition at line 990 of file chan_dahdi.c.

991{
992 /* recall that if a field is not included here it is initialized
993 * to 0 or equivalent
994 */
995 struct dahdi_chan_conf conf = {
996#ifdef HAVE_PRI
997 .pri.pri = {
998 .nsf = PRI_NSF_NONE,
999 .switchtype = PRI_SWITCH_NI2,
1000 .dialplan = PRI_UNKNOWN + 1,
1001 .localdialplan = PRI_NATIONAL_ISDN + 1,
1002 .nodetype = PRI_CPE,
1003 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
1004
1005#if defined(HAVE_PRI_CCSS)
1006 .cc_ptmp_recall_mode = 1,/* specificRecall */
1007 .cc_qsig_signaling_link_req = 1,/* retain */
1008 .cc_qsig_signaling_link_rsp = 1,/* retain */
1009#endif /* defined(HAVE_PRI_CCSS) */
1010
1011 .minunused = 2,
1012 .idleext = "",
1013 .idledial = "",
1014 .internationalprefix = "",
1015 .nationalprefix = "",
1016 .localprefix = "",
1017 .privateprefix = "",
1018 .unknownprefix = "",
1019 .colp_send = SIG_PRI_COLP_UPDATE,
1020 .resetinterval = -1,
1021 },
1022#endif
1023#if defined(HAVE_SS7)
1024 .ss7.ss7 = {
1025 .called_nai = SS7_NAI_NATIONAL,
1026 .calling_nai = SS7_NAI_NATIONAL,
1027 .internationalprefix = "",
1028 .nationalprefix = "",
1029 .subscriberprefix = "",
1030 .unknownprefix = "",
1031 .networkroutedprefix = ""
1032 },
1033#endif /* defined(HAVE_SS7) */
1034#ifdef HAVE_OPENR2
1035 .mfcr2 = {
1036 .variant = OR2_VAR_ITU,
1037 .mfback_timeout = -1,
1038 .metering_pulse_timeout = -1,
1039 .max_ani = 10,
1040 .max_dnis = 4,
1041 .get_ani_first = -1,
1042#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
1043 .skip_category_request = -1,
1044#endif
1045 .call_files = 0,
1046 .allow_collect_calls = 0,
1047 .charge_calls = 1,
1048 .accept_on_offer = 1,
1049 .forced_release = 0,
1050 .double_answer = 0,
1051 .immediate_accept = -1,
1052#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
1053 .dtmf_dialing = -1,
1054 .dtmf_detection = -1,
1055 .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
1056 .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
1057#endif
1058#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
1059 .dtmf_end_timeout = -1,
1060#endif
1061 .logdir = "",
1062 .r2proto_file = "",
1063 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
1064 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
1065 },
1066#endif
1067 .chan = {
1068 .context = "default",
1069 .immediatering = 1,
1070 .cid_num = "",
1071 .cid_name = "",
1072 .cid_tag = "",
1073 .mohinterpret = "default",
1074 .mohsuggest = "",
1075 .parkinglot = "",
1076 .transfertobusy = 1,
1077 .dialmode = 0,
1078
1079 .ani_info_digits = 2,
1080 .ani_wink_time = 1000,
1081 .ani_timeout = 10000,
1082
1083 .cid_signalling = CID_SIG_BELL,
1084 .cid_start = CID_START_RING,
1085 .dahditrcallerid = 0,
1086 .use_callerid = 1,
1087 .sig = -1,
1088 .outsigmod = -1,
1089
1090 .cid_rxgain = +5.0,
1091
1092 .tonezone = -1,
1093
1094 .echocancel.head.tap_length = 1,
1095
1096 .busycount = 3,
1097
1098 .accountcode = "",
1099
1100 .mailbox = "",
1101
1102#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
1103 .mwisend_fsk = 1,
1104#endif
1105 .polarityonanswerdelay = 600,
1106
1107 .sendcalleridafter = DEFAULT_CIDRINGS,
1108
1109 .buf_policy = DAHDI_POLICY_IMMEDIATE,
1110 .buf_no = numbufs,
1111 .usefaxbuffers = 0,
1112 .cc_params = ast_cc_config_params_init(),
1113 .firstdigit_timeout = ANALOG_FIRST_DIGIT_TIMEOUT,
1114 .interdigit_timeout = ANALOG_INTER_DIGIT_TIMEOUT,
1115 .matchdigit_timeout = ANALOG_MATCH_DIGIT_TIMEOUT,
1116 },
1117 .timing = {
1118 .prewinktime = -1,
1119 .preflashtime = -1,
1120 .winktime = -1,
1121 .flashtime = -1,
1122 .starttime = -1,
1123 .rxwinktime = -1,
1124 .rxflashtime = -1,
1125 .debouncetime = -1
1126 },
1127 .is_sig_auto = 1,
1128 .ignore_failed_channels = 1,
1129 .smdi_port = "/dev/ttyS0",
1130 };
1131
1132 return conf;
1133}
#define CID_SIG_BELL
Definition: callerid.h:60
#define ast_cc_config_params_init()
Allocate and initialize an ast_cc_config_params structure.
Definition: ccss.h:135
static int numbufs
Definition: chan_dahdi.c:731
#define DEFAULT_CIDRINGS
Typically, how many rings before we should send Caller*ID.
Definition: chan_dahdi.c:640
#define ANALOG_INTER_DIGIT_TIMEOUT
Default time (ms) to detect following digits.
Definition: sig_analog.h:40
#define ANALOG_MATCH_DIGIT_TIMEOUT
Default time (ms) to wait, in case of ambiguous match.
Definition: sig_analog.h:42
#define ANALOG_FIRST_DIGIT_TIMEOUT
Default time (ms) to detect first digit.
Definition: sig_analog.h:38
@ SIG_PRI_COLP_UPDATE
Definition: sig_pri.h:441
#define DAHDI_CHAN_MAPPING_PHYSICAL
Definition: sig_pri.h:247
Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section o...
Definition: chan_dahdi.c:952

References ANALOG_FIRST_DIGIT_TIMEOUT, ANALOG_INTER_DIGIT_TIMEOUT, ANALOG_MATCH_DIGIT_TIMEOUT, ast_cc_config_params_init, CID_SIG_BELL, CID_START_RING, DAHDI_CHAN_MAPPING_PHYSICAL, DEFAULT_CIDRINGS, numbufs, and SIG_PRI_COLP_UPDATE.

Referenced by dahdi_create_channel_range(), process_dahdi(), and setup_dahdi().

◆ dahdi_close()

static void dahdi_close ( int  fd)
static

Definition at line 4381 of file chan_dahdi.c.

4382{
4383 if (fd > 0)
4384 close(fd);
4385}

Referenced by dahdi_close_sub().

◆ dahdi_close_sub()

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

Definition at line 4387 of file chan_dahdi.c.

4388{
4389 dahdi_close(chan_pvt->subs[sub_num].dfd);
4390 chan_pvt->subs[sub_num].dfd = -1;
4391}
static void dahdi_close(int fd)
Definition: chan_dahdi.c:4381

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

Referenced by alloc_sub(), destroy_dahdi_pvt(), and unalloc_sub().

◆ dahdi_conf_update()

void dahdi_conf_update ( struct dahdi_pvt p)

Definition at line 4831 of file chan_dahdi.c.

4832{
4833 int needconf = 0;
4834 int x;
4835 int useslavenative;
4836 struct dahdi_pvt *slave = NULL;
4837
4838 useslavenative = isslavenative(p, &slave);
4839 /* Start with the obvious, general stuff */
4840 for (x = 0; x < 3; x++) {
4841 /* Look for three way calls */
4842 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
4843 conf_add(p, &p->subs[x], x, 0);
4844 needconf++;
4845 } else {
4846 conf_del(p, &p->subs[x], x);
4847 }
4848 }
4849 /* If we have a slave, add him to our conference now. or DAX
4850 if this is slave native */
4851 for (x = 0; x < MAX_SLAVES; x++) {
4852 if (p->slaves[x]) {
4853 if (useslavenative)
4854 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
4855 else {
4856 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
4857 needconf++;
4858 }
4859 }
4860 }
4861 /* If we're supposed to be in there, do so now */
4862 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
4863 if (useslavenative)
4864 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
4865 else {
4866 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
4867 needconf++;
4868 }
4869 }
4870 /* If we have a master, add ourselves to his conference */
4871 if (p->master) {
4872 if (isslavenative(p->master, NULL)) {
4874 } else {
4875 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
4876 }
4877 }
4878 if (!needconf) {
4879 /* Nobody is left (or should be left) in our conference.
4880 Kill it. */
4881 p->confno = -1;
4882 }
4883 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
4884}
static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
Definition: chan_dahdi.c:4754
static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
Definition: chan_dahdi.c:4705
static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
Definition: chan_dahdi.c:4773
#define GET_CHANNEL(p)
Definition: chan_dahdi.c:1180
#define MAX_SLAVES
Definition: chan_dahdi.h:95
struct dahdi_pvt * slaves[MAX_SLAVES]
Definition: chan_dahdi.h:134
int inconference
Definition: chan_dahdi.h:136
unsigned int inthreeway
Definition: chan_dahdi.h:91

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, NULL, dahdi_pvt::slaves, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), dahdi_fixup(), dahdi_handle_event(), dahdi_hangup(), dahdi_master_slave_unlink(), mkintf(), and native_start().

◆ dahdi_confmute()

static int dahdi_confmute ( struct dahdi_pvt p,
int  muted 
)
inlinestatic

Definition at line 5187 of file chan_dahdi.c.

5188{
5189 int x, res;
5190
5191 x = muted;
5192#if defined(HAVE_PRI) || defined(HAVE_SS7)
5193 switch (p->sig) {
5194#if defined(HAVE_PRI)
5196 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
5197 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
5198 break;
5199 }
5200 /* Fall through */
5201#endif /* defined(HAVE_PRI) */
5202#if defined(HAVE_SS7)
5203 case SIG_SS7:
5204#endif /* defined(HAVE_SS7) */
5205 {
5206 int y = 1;
5207
5208 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
5209 if (res)
5210 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
5211 p->channel, strerror(errno));
5212 }
5213 break;
5214 default:
5215 break;
5216 }
5217#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
5218 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
5219 if (res < 0)
5220 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
5221 return res;
5222}

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

◆ dahdi_create_channel_range()

static int dahdi_create_channel_range ( int  start,
int  end 
)
static

Definition at line 11515 of file chan_dahdi.c.

11516{
11517 struct dahdi_pvt *cur;
11518 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
11519 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
11521 int ret = RESULT_FAILURE; /* be pessimistic */
11522
11523 ast_debug(1, "channel range caps: %d - %d\n", start, end);
11525 for (cur = iflist; cur; cur = cur->next) {
11526 if (cur->channel >= start && cur->channel <= end) {
11528 "channel range %d-%d is occupied\n",
11529 start, end);
11530 goto out;
11531 }
11532 }
11533#ifdef HAVE_PRI
11534 {
11535 int i, x;
11536 for (x = 0; x < NUM_SPANS; x++) {
11537 struct dahdi_pri *pri = pris + x;
11538
11539 if (!pris[x].pri.pvts[0]) {
11540 break;
11541 }
11542 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
11543 int channo = pri->dchannels[i];
11544
11545 if (!channo) {
11546 break;
11547 }
11548 if (!pri->pri.fds[i]) {
11549 break;
11550 }
11551 if (channo >= start && channo <= end) {
11553 "channel range %d-%d is occupied by span %d\n",
11554 start, end, x + 1);
11555 goto out;
11556 }
11557 }
11558 }
11559 }
11560#endif
11561 if (!default_conf.chan.cc_params || !base_conf.chan.cc_params ||
11562 !conf.chan.cc_params) {
11563 goto out;
11564 }
11565 default_conf.wanted_channels_start = start;
11566 base_conf.wanted_channels_start = start;
11567 conf.wanted_channels_start = start;
11568 default_conf.wanted_channels_end = end;
11569 base_conf.wanted_channels_end = end;
11570 conf.wanted_channels_end = end;
11571 if (setup_dahdi_int(0, &default_conf, &base_conf, &conf) == 0) {
11572 ret = RESULT_SUCCESS;
11573 }
11574out:
11577 ast_cc_config_params_destroy(conf.chan.cc_params);
11579 return ret;
11580}
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition: ccss.c:692
static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
Definition: chan_dahdi.c:19944
static struct dahdi_chan_conf dahdi_chan_conf_default(void)
Definition: chan_dahdi.c:990
#define RESULT_SUCCESS
Definition: cli.h:40
#define RESULT_FAILURE
Definition: cli.h:42
char * end
Definition: eagi_proxy.c:73
int wanted_channels_end
Don't create channels above this number (infinity by default)
Definition: chan_dahdi.c:986
struct dahdi_pvt chan
Definition: chan_dahdi.c:953
int wanted_channels_start
Don't create channels below this number.
Definition: chan_dahdi.c:980
FILE * out
Definition: utils/frame.c:33

References ast_cc_config_params_destroy(), ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::cc_params, dahdi_chan_conf::chan, dahdi_pvt::channel, dahdi_chan_conf_default(), end, iflist, iflock, LOG_ERROR, dahdi_pvt::next, NUM_SPANS, out, RESULT_FAILURE, RESULT_SUCCESS, setup_dahdi_int(), SIG_PRI_NUM_DCHANS, dahdi_chan_conf::wanted_channels_end, and dahdi_chan_conf::wanted_channels_start.

Referenced by dahdi_create_channels().

◆ dahdi_create_channels()

static char * dahdi_create_channels ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 15752 of file chan_dahdi.c.

15753{
15754 int start;
15755 int end;
15756 int ret;
15757
15758 switch (cmd) {
15759 case CLI_INIT:
15760 e->command = "dahdi create channels";
15761 e->usage = "Usage: dahdi create channels <from> [<to>] - a range of channels\n"
15762 " dahdi create channels new - add channels not yet created\n"
15763 "For ISDN and SS7 the range should include complete spans.\n";
15764 return NULL;
15765 case CLI_GENERATE:
15766 return NULL;
15767 }
15768 if ((a->argc < 4) || a->argc > 5) {
15769 return CLI_SHOWUSAGE;
15770 }
15771 if (a->argc == 4 && !strcmp(a->argv[3], "new")) {
15772 ret = dahdi_create_channel_range(0, 0);
15773 return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15774 }
15775 start = atoi(a->argv[3]);
15776 if (start <= 0) {
15777 ast_cli(a->fd, "Invalid starting channel number '%s'.\n",
15778 a->argv[3]);
15779 return CLI_FAILURE;
15780 }
15781 if (a->argc == 5) {
15782 end = atoi(a->argv[4]);
15783 if (end <= 0) {
15784 ast_cli(a->fd, "Invalid ending channel number '%s'.\n",
15785 a->argv[4]);
15786 return CLI_FAILURE;
15787 }
15788 } else {
15789 end = start;
15790 }
15791 if (end < start) {
15792 ast_cli(a->fd,
15793 "range end (%d) is smaller than range start (%d)\n",
15794 end, start);
15795 return CLI_FAILURE;
15796 }
15797 ret = dahdi_create_channel_range(start, end);
15798 return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15799}
static int dahdi_create_channel_range(int start, int end)
Definition: chan_dahdi.c:11515
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
static struct test_val a

References a, ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_create_channel_range(), end, NULL, RESULT_SUCCESS, and ast_cli_entry::usage.

◆ dahdi_destroy_channel_range()

static void dahdi_destroy_channel_range ( int  start,
int  end 
)
static

Definition at line 11433 of file chan_dahdi.c.

11434{
11435 struct dahdi_pvt *cur;
11436 struct dahdi_pvt *next;
11437 int destroyed_first = 0;
11438 int destroyed_last = 0;
11439
11441 ast_debug(1, "range: %d-%d\n", start, end);
11442 for (cur = iflist; cur; cur = next) {
11443 next = cur->next;
11444 if (cur->channel >= start && cur->channel <= end) {
11445 int x = DAHDI_FLASH;
11446
11447 if (cur->channel > destroyed_last) {
11448 destroyed_last = cur->channel;
11449 }
11450 if (destroyed_first < 1 || cur->channel < destroyed_first) {
11451 destroyed_first = cur->channel;
11452 }
11453 ast_debug(3, "Destroying %d\n", cur->channel);
11454 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11455 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11456
11457 destroy_channel(cur, 1);
11459 }
11460 }
11462 if (destroyed_first > start || destroyed_last < end) {
11463 ast_debug(1, "Asked to destroy %d-%d, destroyed %d-%d,\n",
11464 start, end, destroyed_first, destroyed_last);
11465 }
11466}
static void destroy_channel(struct dahdi_pvt *cur, int now)
Definition: chan_dahdi.c:5895
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
struct ast_module * self
Definition: module.h:342

References ast_debug, ast_module_unref, ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, destroy_channel(), dahdi_subchannel::dfd, end, iflist, iflock, dahdi_pvt::next, ast_module_info::self, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_destroy_channels(), and do_monitor().

◆ dahdi_destroy_channels()

static char * dahdi_destroy_channels ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 15708 of file chan_dahdi.c.

15709{
15710 int start;
15711 int end;
15712 switch (cmd) {
15713 case CLI_INIT:
15714 e->command = "dahdi destroy channels";
15715 e->usage =
15716 "Usage: dahdi destroy channels <from_channel> [<to_channel>]\n"
15717 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15718 return NULL;
15719 case CLI_GENERATE:
15720 return NULL;
15721 }
15722 if ((a->argc < 4) || a->argc > 5) {
15723 return CLI_SHOWUSAGE;
15724 }
15725 start = atoi(a->argv[3]);
15726 if (start < 1) {
15727 ast_cli(a->fd, "Invalid starting channel number %s.\n",
15728 a->argv[4]);
15729 return CLI_FAILURE;
15730 }
15731 if (a->argc == 5) {
15732 end = atoi(a->argv[4]);
15733 if (end < 1) {
15734 ast_cli(a->fd, "Invalid ending channel number %s.\n",
15735 a->argv[4]);
15736 return CLI_FAILURE;
15737 }
15738 } else {
15739 end = start;
15740 }
15741
15742 if (end < start) {
15743 ast_cli(a->fd,
15744 "range end (%d) is smaller than range start (%d)\n",
15745 end, start);
15746 return CLI_FAILURE;
15747 }
15749 return CLI_SUCCESS;
15750}
static void dahdi_destroy_channel_range(int start, int end)
Definition: chan_dahdi.c:11433

References a, ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_destroy_channel_range(), end, NULL, and ast_cli_entry::usage.

◆ dahdi_devicestate()

static int dahdi_devicestate ( const char *  data)
static

Definition at line 14072 of file chan_dahdi.c.

14073{
14074#if defined(HAVE_PRI)
14075 const char *device;
14076 unsigned span;
14077 int res;
14078
14079 device = data;
14080
14081 if (*device != 'I') {
14082 /* The request is not for an ISDN span device. */
14083 return AST_DEVICE_UNKNOWN;
14084 }
14085 res = sscanf(device, "I%30u", &span);
14086 if (res != 1 || !span || NUM_SPANS < span) {
14087 /* Bad format for ISDN span device name. */
14088 return AST_DEVICE_UNKNOWN;
14089 }
14090 device = strchr(device, '/');
14091 if (!device) {
14092 /* Bad format for ISDN span device name. */
14093 return AST_DEVICE_UNKNOWN;
14094 }
14095
14096 /*
14097 * Since there are currently no other span devstate's defined,
14098 * it must be congestion.
14099 */
14100#if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14101 ++device;
14102 if (!strcmp(device, "congestion"))
14103#endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14104 {
14105 return pris[span - 1].pri.congestion_devstate;
14106 }
14107#if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14108 else if (!strcmp(device, "threshold")) {
14109 return pris[span - 1].pri.threshold_devstate;
14110 }
14111 return AST_DEVICE_UNKNOWN;
14112#endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14113#else
14114 return AST_DEVICE_UNKNOWN;
14115#endif /* defined(HAVE_PRI) */
14116}
@ AST_DEVICE_UNKNOWN
Definition: devicestate.h:53

References AST_DEVICE_UNKNOWN, and NUM_SPANS.

◆ dahdi_dial_str()

static int dahdi_dial_str ( struct dahdi_pvt pvt,
int  operation,
const char *  dial_str 
)
static

Definition at line 1350 of file chan_dahdi.c.

1351{
1352 int res;
1353 int offset;
1354 const char *pos;
1355 struct dahdi_dialoperation zo = {
1356 .op = operation,
1357 };
1358
1359 /* Convert the W's to ww. */
1360 pos = dial_str;
1361 for (offset = 0; offset < sizeof(zo.dialstr) - 1; ++offset) {
1362 if (!*pos) {
1363 break;
1364 }
1365 if (*pos == 'W') {
1366 /* Convert 'W' to "ww" */
1367 ++pos;
1368 if (offset >= sizeof(zo.dialstr) - 3) {
1369 /* No room to expand */
1370 break;
1371 }
1372 zo.dialstr[offset] = 'w';
1373 ++offset;
1374 zo.dialstr[offset] = 'w';
1375 continue;
1376 }
1377 zo.dialstr[offset] = *pos++;
1378 }
1379 /* The zo initialization has already terminated the dialstr. */
1380
1381 ast_debug(1, "Channel %d: Dial str '%s' expanded to '%s' sent to DAHDI_DIAL.\n",
1382 pvt->channel, dial_str, zo.dialstr);
1383 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
1384 if (res) {
1385 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
1386 pvt->channel, dial_str, strerror(errno));
1387 }
1388
1389 return res;
1390}

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

Referenced by dahdi_digit_begin(), dahdi_handle_event(), dahdi_read(), and my_dial_digits().

◆ dahdi_digit_begin()

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

Definition at line 4485 of file chan_dahdi.c.

4486{
4487 struct dahdi_pvt *pvt;
4488 int idx;
4489 int dtmf;
4490 int res;
4491
4492 pvt = ast_channel_tech_pvt(chan);
4493
4494 ast_mutex_lock(&pvt->lock);
4495
4496 idx = dahdi_get_index(chan, pvt, 0);
4497
4498 if ((idx != SUB_REAL) || !pvt->owner)
4499 goto out;
4500
4501#ifdef HAVE_PRI
4502 switch (pvt->sig) {
4504 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
4505 if (!res)
4506 goto out;
4507 break;
4508 default:
4509 break;
4510 }
4511#endif
4512 dtmf = digit_to_dtmfindex(digit);
4513 if (dtmf == -1) {
4514 /* Not a valid DTMF digit */
4515 goto out;
4516 }
4517
4518 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
4519 char dial_str[] = { 'T', digit, '\0' };
4520
4521 res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
4522 if (!res) {
4523 pvt->dialing = 1;
4524 }
4525 } else {
4526 pvt->dialing = 1;
4527 pvt->begindigit = digit;
4528
4529 /* Flush the write buffer in DAHDI to start sending the digit immediately. */
4530 dtmf = DAHDI_FLUSH_WRITE;
4531 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &dtmf);
4532 if (res) {
4533 ast_log(LOG_WARNING, "Unable to flush the DAHDI write buffer to send DTMF on channel %d: %s\n",
4534 pvt->channel, strerror(errno));
4535 }
4536
4537 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
4538 ast_channel_name(chan), digit);
4539 }
4540
4541out:
4542 ast_mutex_unlock(&pvt->lock);
4543
4544 return 0;
4545}
char digit
static int digit_to_dtmfindex(char digit)
Definition: chan_dahdi.c:4469
static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
Definition: chan_dahdi.c:1350
int sig_pri_digit_begin(struct sig_pri_chan *pvt, struct ast_channel *ast, char digit)
unsigned int pulse
TRUE if we will pulse dial.
Definition: chan_dahdi.h:354
char begindigit
DTMF digit in progress. 0 when no digit in progress.
Definition: chan_dahdi.h:761

References ast_channel_name(), ast_channel_tech_pvt(), ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::begindigit, dahdi_pvt::channel, dahdi_dial_str(), dahdi_get_index, dahdi_subchannel::dfd, dahdi_pvt::dialing, digit, digit_to_dtmfindex(), errno, dahdi_pvt::lock, LOG_WARNING, out, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, sig_pri_digit_begin(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.

◆ dahdi_digit_end()

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

Definition at line 4547 of file chan_dahdi.c.

4548{
4549 struct dahdi_pvt *pvt;
4550 int res = 0;
4551 int idx;
4552 int x;
4553
4554 pvt = ast_channel_tech_pvt(chan);
4555
4556 ast_mutex_lock(&pvt->lock);
4557
4558 idx = dahdi_get_index(chan, pvt, 0);
4559
4560 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
4561 goto out;
4562
4563#ifdef HAVE_PRI
4564 /* This means that the digit was already sent via PRI signalling */
4565 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
4566 goto out;
4567 }
4568#endif
4569
4570 if (pvt->begindigit) {
4571 x = -1;
4572 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
4573 ast_channel_name(chan), digit);
4574 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
4575 pvt->dialing = 0;
4576 pvt->begindigit = 0;
4577 }
4578
4579out:
4580 ast_mutex_unlock(&pvt->lock);
4581
4582 return res;
4583}

References ast_channel_name(), ast_channel_tech_pvt(), 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, digit, dahdi_pvt::lock, out, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.

◆ dahdi_dnd()

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)
flagon 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 9831 of file chan_dahdi.c.

9832{
9833 if (dahdi_analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
9834 return analog_dnd(dahdichan->sig_pvt, flag);
9835 }
9836
9837 if (flag == -1) {
9838 return dahdichan->dnd;
9839 }
9840
9841 /* Do not disturb */
9842 dahdichan->dnd = flag;
9843 ast_verb(3, "%s DND on channel %d\n",
9844 flag? "Enabled" : "Disabled",
9845 dahdichan->channel);
9846 publish_dnd_state(dahdichan->channel, flag ? "enabled" : "disabled");
9847 return 0;
9848}
static void publish_dnd_state(int channel, const char *status)
Definition: chan_dahdi.c:9802
long int flag
Definition: f2c.h:83
int analog_dnd(struct analog_pvt *p, int flag)
Definition: sig_analog.c:4165
unsigned int dnd
TRUE if Do-Not-Disturb is enabled, present only for non sig_analog.
Definition: chan_dahdi.h:262

References analog_dnd(), ast_verb, dahdi_pvt::channel, dahdi_analog_lib_handles(), dahdi_pvt::dnd, dahdi_pvt::oprmode, publish_dnd_state(), 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().

◆ dahdi_dtmf_detect_disable()

void dahdi_dtmf_detect_disable ( struct dahdi_pvt p)

Definition at line 6751 of file chan_dahdi.c.

6752{
6753 int val = 0;
6754
6755 p->ignoredtmf = 1;
6756
6757 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6758
6759 if (!p->hardwaredtmf && p->dsp) {
6760 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
6762 }
6763}
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1768
unsigned int ignoredtmf
TRUE if DTMF detection is disabled.
Definition: chan_dahdi.h:310
int dsp_features
DSP feature flags: DSP_FEATURE_xxx.
Definition: chan_dahdi.h:738
Definition: ast_expr2.c:325

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

Referenced by dahdi_setoption(), and native_start().

◆ dahdi_dtmf_detect_enable()

void dahdi_dtmf_detect_enable ( struct dahdi_pvt p)

Definition at line 6765 of file chan_dahdi.c.

6766{
6767 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
6768
6769 if (p->channel == CHAN_PSEUDO)
6770 return;
6771
6772 p->ignoredtmf = 0;
6773
6774 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6775
6776 if (!p->hardwaredtmf && p->dsp) {
6779 }
6780}
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28

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_setoption(), and native_stop().

◆ dahdi_ec_disable()

void dahdi_ec_disable ( struct dahdi_pvt p)

Definition at line 4958 of file chan_dahdi.c.

4959{
4960 int res;
4961
4962 if (p->echocanon) {
4963 struct dahdi_echocanparams ecp = { .tap_length = 0 };
4964
4965 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
4966
4967 if (res)
4968 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
4969 else
4970 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
4971 }
4972
4973 p->echocanon = 0;
4974}
unsigned int echocanon
TRUE if echo cancellation is turned on.
Definition: chan_dahdi.h:272

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_func_write(), dahdi_handle_event(), dahdi_hangup(), dahdi_setoption(), handle_init_event(), my_set_echocanceller(), and native_start().

◆ dahdi_ec_enable()

void dahdi_ec_enable ( struct dahdi_pvt p)

Definition at line 4886 of file chan_dahdi.c.

4887{
4888 int res;
4889 if (!p)
4890 return;
4891 if (p->echocanon) {
4892 ast_debug(1, "Echo cancellation already on\n");
4893 return;
4894 }
4895 if (p->digital) {
4896 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
4897 return;
4898 }
4899 if (p->echocancel.head.tap_length) {
4900#if defined(HAVE_PRI) || defined(HAVE_SS7)
4901 switch (p->sig) {
4902#if defined(HAVE_PRI)
4904 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
4905 /*
4906 * PRI nobch pseudo channel. Does not need ec anyway.
4907 * Does not handle ioctl(DAHDI_AUDIOMODE)
4908 */
4909 return;
4910 }
4911 /* Fall through */
4912#endif /* defined(HAVE_PRI) */
4913#if defined(HAVE_SS7)
4914 case SIG_SS7:
4915#endif /* defined(HAVE_SS7) */
4916 {
4917 int x = 1;
4918
4919 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
4920 if (res)
4922 "Unable to enable audio mode on channel %d (%s)\n",
4923 p->channel, strerror(errno));
4924 }
4925 break;
4926 default:
4927 break;
4928 }
4929#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
4930 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
4931 if (res) {
4932 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
4933 } else {
4934 p->echocanon = 1;
4935 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
4936 }
4937 } else
4938 ast_debug(1, "No echo cancellation requested\n");
4939}
struct dahdi_pvt::@115 echocancel
Echo cancel parameters.
struct dahdi_echocanparams head
Definition: chan_dahdi.h:627
unsigned int digital
TRUE if the transfer capability of the call is digital.
Definition: chan_dahdi.h:260

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_func_write(), dahdi_handle_event(), dahdi_setoption(), handle_init_event(), my_set_echocanceller(), and native_stop().

◆ dahdi_exception()

static struct ast_frame * dahdi_exception ( struct ast_channel ast)
static

Definition at line 8761 of file chan_dahdi.c.

8762{
8763 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8764 struct ast_frame *f;
8765 ast_mutex_lock(&p->lock);
8766 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8767 struct analog_pvt *analog_p = p->sig_pvt;
8768 f = analog_exception(analog_p, ast);
8769 } else {
8770 f = __dahdi_exception(ast);
8771 }
8773 return f;
8774}
static struct ast_frame * __dahdi_exception(struct ast_channel *ast)
Definition: chan_dahdi.c:8639
struct ast_frame * analog_exception(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:3673

References __dahdi_exception(), analog_exception(), ast_channel_tech_pvt(), ast_mutex_lock, ast_mutex_unlock, dahdi_analog_lib_handles(), dahdi_pvt::lock, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, and dahdi_pvt::sig_pvt.

◆ dahdi_fake_event()

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

Definition at line 16727 of file chan_dahdi.c.

16728{
16729 if (p) {
16730 switch (mode) {
16731 case TRANSFER:
16732 p->fake_event = DAHDI_EVENT_WINKFLASH;
16733 break;
16734 case HANGUP:
16735 p->fake_event = DAHDI_EVENT_ONHOOK;
16736 break;
16737 default:
16738 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));
16739 }
16740 }
16741 return 0;
16742}

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

◆ dahdi_fixup()

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

Definition at line 7412 of file chan_dahdi.c.

7413{
7414 struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
7415 int x;
7416
7417 ast_mutex_lock(&p->lock);
7418
7419 ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
7420 if (p->owner == oldchan) {
7421 p->owner = newchan;
7422 }
7423 for (x = 0; x < 3; x++) {
7424 if (p->subs[x].owner == oldchan) {
7425 if (!x) {
7427 }
7428 p->subs[x].owner = newchan;
7429 }
7430 }
7431 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
7432 analog_fixup(oldchan, newchan, p->sig_pvt);
7433#if defined(HAVE_PRI)
7434 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
7435 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
7436#endif /* defined(HAVE_PRI) */
7437#if defined(HAVE_SS7)
7438 } else if (p->sig == SIG_SS7) {
7439 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
7440#endif /* defined(HAVE_SS7) */
7441 }
7443
7445
7446 if (ast_channel_state(newchan) == AST_STATE_RINGING) {
7448 }
7449 return 0;
7450}
static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Definition: chan_dahdi.c:9340
void dahdi_master_slave_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
Definition: chan_dahdi.c:7332
@ AST_CONTROL_RINGING
int analog_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, void *newp)
Definition: sig_analog.c:4127
void sig_pri_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_pri_chan *pchan)
void sig_ss7_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_ss7_chan *pchan)

References analog_fixup(), ast_channel_name(), ast_channel_tech_pvt(), AST_CONTROL_RINGING, ast_debug, ast_mutex_lock, ast_mutex_unlock, AST_STATE_RINGING, dahdi_pvt::channel, dahdi_analog_lib_handles(), dahdi_conf_update(), dahdi_indicate(), dahdi_master_slave_unlink(), dahdi_sig_pri_lib_handles(), dahdi_pvt::lock, NULL, 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(), and dahdi_pvt::subs.

◆ dahdi_func_read()

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

Definition at line 7050 of file chan_dahdi.c.

7051{
7052 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
7053 int res = 0;
7054
7055 if (!p) {
7056 /* No private structure! */
7057 *buf = '\0';
7058 return -1;
7059 }
7060
7061 if (!strcasecmp(data, "rxgain")) {
7062 ast_mutex_lock(&p->lock);
7063 snprintf(buf, len, "%f", p->rxgain);
7065 } else if (!strcasecmp(data, "txgain")) {
7066 ast_mutex_lock(&p->lock);
7067 snprintf(buf, len, "%f", p->txgain);
7069 } else if (!strcasecmp(data, "dahdi_channel")) {
7070 ast_mutex_lock(&p->lock);
7071 snprintf(buf, len, "%d", p->channel);
7073 } else if (!strcasecmp(data, "dahdi_span")) {
7074 ast_mutex_lock(&p->lock);
7075 snprintf(buf, len, "%d", p->span);
7077 } else if (!strcasecmp(data, "dahdi_group")) {
7078 ast_mutex_lock(&p->lock);
7079 snprintf(buf, len, "%llu", p->group);
7081 } else if (!strcasecmp(data, "dahdi_type")) {
7082 ast_mutex_lock(&p->lock);
7083 switch (p->sig) {
7084#if defined(HAVE_OPENR2)
7085 case SIG_MFCR2:
7086 ast_copy_string(buf, "mfc/r2", len);
7087 break;
7088#endif /* defined(HAVE_OPENR2) */
7089#if defined(HAVE_PRI)
7091 ast_copy_string(buf, "pri", len);
7092 break;
7093#endif /* defined(HAVE_PRI) */
7094 case 0:
7095 ast_copy_string(buf, "pseudo", len);
7096 break;
7097#if defined(HAVE_SS7)
7098 case SIG_SS7:
7099 ast_copy_string(buf, "ss7", len);
7100 break;
7101#endif /* defined(HAVE_SS7) */
7102 default:
7103 /* The only thing left is analog ports. */
7104 ast_copy_string(buf, "analog", len);
7105 break;
7106 }
7108#if defined(HAVE_PRI)
7109#if defined(HAVE_PRI_REVERSE_CHARGE)
7110 } else if (!strcasecmp(data, "reversecharge")) {
7111 ast_mutex_lock(&p->lock);
7112 switch (p->sig) {
7114 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
7115 break;
7116 default:
7117 *buf = '\0';
7118 res = -1;
7119 break;
7120 }
7122#endif
7123#if defined(HAVE_PRI_SETUP_KEYPAD)
7124 } else if (!strcasecmp(data, "keypad_digits")) {
7125 ast_mutex_lock(&p->lock);
7126 switch (p->sig) {
7128 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
7129 len);
7130 break;
7131 default:
7132 *buf = '\0';
7133 res = -1;
7134 break;
7135 }
7137#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
7138 } else if (!strcasecmp(data, "no_media_path")) {
7139 ast_mutex_lock(&p->lock);
7140 switch (p->sig) {
7142 /*
7143 * TRUE if the call is on hold or is call waiting because
7144 * there is no media path available.
7145 */
7146 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
7147 break;
7148 default:
7149 *buf = '\0';
7150 res = -1;
7151 break;
7152 }
7154#endif /* defined(HAVE_PRI) */
7155 } else if (!strcasecmp(data, "dialmode")) {
7156 struct analog_pvt *analog_p;
7157 ast_mutex_lock(&p->lock);
7158 analog_p = p->sig_pvt;
7159 /* Hardcode p->radio and p->oprmode as 0 since we're using this to check for analogness, not the handler */
7160 if (dahdi_analog_lib_handles(p->sig, 0, 0) && analog_p) {
7161 switch (analog_p->dialmode) {
7163 ast_copy_string(buf, "both", len);
7164 break;
7166 ast_copy_string(buf, "pulse", len);
7167 break;
7169 ast_copy_string(buf, "dtmf", len);
7170 break;
7172 ast_copy_string(buf, "none", len);
7173 break;
7174 }
7175 } else {
7176 ast_log(LOG_WARNING, "%s only supported on analog channels\n", data);
7177 *buf = '\0';
7178 res = -1;
7179 }
7181 } else {
7182 *buf = '\0';
7183 res = -1;
7184 }
7185
7186 return res;
7187}
@ ANALOG_DIALMODE_DTMF
Definition: sig_analog.h:122
@ ANALOG_DIALMODE_PULSE
Definition: sig_analog.h:121
@ ANALOG_DIALMODE_NONE
Definition: sig_analog.h:123
@ ANALOG_DIALMODE_BOTH
Definition: sig_analog.h:120
enum analog_dialmode dialmode
Definition: sig_analog.h:321

References ANALOG_DIALMODE_BOTH, ANALOG_DIALMODE_DTMF, ANALOG_DIALMODE_NONE, ANALOG_DIALMODE_PULSE, ast_channel_tech_pvt(), ast_copy_string(), ast_log, ast_mutex_lock, ast_mutex_unlock, buf, dahdi_pvt::channel, dahdi_analog_lib_handles(), analog_pvt::dialmode, dahdi_pvt::group, len(), dahdi_pvt::lock, LOG_WARNING, dahdi_pvt::rxgain, dahdi_pvt::sig, SIG_MFCR2, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, dahdi_pvt::span, and dahdi_pvt::txgain.

◆ dahdi_func_write()

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

Definition at line 7219 of file chan_dahdi.c.

7220{
7221 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
7222 int res = 0;
7223
7224 if (!p) {
7225 /* No private structure! */
7226 return -1;
7227 }
7228
7229 if (!strcasecmp(data, "buffers")) {
7230 int num_bufs, policy;
7231
7232 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
7233 struct dahdi_bufferinfo bi = {
7234 .txbufpolicy = policy,
7235 .rxbufpolicy = policy,
7236 .bufsize = p->bufsize,
7237 .numbufs = num_bufs,
7238 };
7239 int bpres;
7240
7241 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7242 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
7243 } else {
7244 p->bufferoverrideinuse = 1;
7245 }
7246 } else {
7247 res = -1;
7248 }
7249 } else if (!strcasecmp(data, "echocan_mode")) {
7250 if (!strcasecmp(value, "on")) {
7251 ast_mutex_lock(&p->lock);
7252 dahdi_ec_enable(p);
7254 } else if (!strcasecmp(value, "off")) {
7255 ast_mutex_lock(&p->lock);
7258#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7259 } else if (!strcasecmp(value, "fax")) {
7260 int blah = 1;
7261
7262 ast_mutex_lock(&p->lock);
7263 if (!p->echocanon) {
7264 dahdi_ec_enable(p);
7265 }
7266 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
7267 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
7268 }
7270 } else if (!strcasecmp(value, "voice")) {
7271 int blah = 0;
7272
7273 ast_mutex_lock(&p->lock);
7274 if (!p->echocanon) {
7275 dahdi_ec_enable(p);
7276 }
7277 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
7278 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
7279 }
7281#endif
7282 } else {
7283 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
7284 res = -1;
7285 }
7286 } else if (!strcasecmp(data, "dialmode")) {
7287 struct analog_pvt *analog_p;
7288
7289 ast_mutex_lock(&p->lock);
7290 analog_p = p->sig_pvt;
7291 if (!dahdi_analog_lib_handles(p->sig, 0, 0) || !analog_p) {
7292 ast_log(LOG_WARNING, "%s only supported on analog channels\n", data);
7294 return -1;
7295 }
7296 /* analog pvt is used for pulse dialing, so update both */
7297 if (!strcasecmp(value, "pulse")) {
7298 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_PULSE;
7299 } else if (!strcasecmp(value, "dtmf") || !strcasecmp(value, "tone")) {
7300 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_DTMF;
7301 } else if (!strcasecmp(value, "none")) {
7302 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_NONE;
7303 } else if (!strcasecmp(value, "both")) {
7304 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_BOTH;
7305 } else {
7306 ast_log(LOG_WARNING, "'%s' is an invalid setting for %s\n", value, data);
7307 res = -1;
7308 }
7310 } else if (!strcasecmp(data, "waitfordialtone")) {
7311 if (ast_strlen_zero(value)) {
7312 ast_log(LOG_WARNING, "waitfordialtone requires a duration in ms\n");
7313 return -1;
7314 }
7315
7316 ast_mutex_lock(&p->lock);
7317 if (!CANPROGRESSDETECT(p)) {
7318 ast_log(LOG_WARNING, "%s only supported on analog trunks\n", data);
7320 return -1;
7321 }
7322 /* Only set the temp waitfordialtone setting, not the permanent one. */
7323 p->waitfordialtonetemp = atoi(value);
7325 } else {
7326 res = -1;
7327 }
7328
7329 return res;
7330}
#define CANPROGRESSDETECT(p)
Definition: chan_dahdi.c:715
static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
Definition: chan_dahdi.c:7190
unsigned int bufferoverrideinuse
Definition: chan_dahdi.h:278
int bufsize
Definition: chan_dahdi.h:138
int waitfordialtonetemp
Transient variable. Same as waitfordialtone, but temporarily set for a specific call,...
Definition: chan_dahdi.h:660
int dialmode
Definition: chan_dahdi.h:149

References ANALOG_DIALMODE_BOTH, ANALOG_DIALMODE_DTMF, ANALOG_DIALMODE_NONE, ANALOG_DIALMODE_PULSE, ast_channel_tech_pvt(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, CANPROGRESSDETECT, dahdi_pvt::channel, dahdi_analog_lib_handles(), dahdi_ec_disable(), dahdi_ec_enable(), dahdi_subchannel::dfd, dahdi_pvt::dialmode, analog_pvt::dialmode, dahdi_pvt::echocanon, errno, dahdi_pvt::lock, LOG_WARNING, parse_buffers_policy(), dahdi_pvt::sig, dahdi_pvt::sig_pvt, SUB_REAL, dahdi_pvt::subs, value, and dahdi_pvt::waitfordialtonetemp.

◆ dahdi_get_event()

static int dahdi_get_event ( int  fd)
inlinestatic

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 773 of file chan_dahdi.c.

774{
775 int j;
776 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
777 return -1;
778 return j;
779}

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

◆ dahdi_handle_dtmf()

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

Definition at line 7582 of file chan_dahdi.c.

7583{
7584 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7585 struct ast_frame *f = *dest;
7586
7587 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
7588 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
7589 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
7590
7591 if (p->confirmanswer) {
7592 if (f->frametype == AST_FRAME_DTMF_END) {
7593 ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
7594 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
7595 of a DTMF digit */
7598 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
7599 p->confirmanswer = 0;
7600 } else {
7601 p->subs[idx].f.frametype = AST_FRAME_NULL;
7602 p->subs[idx].f.subclass.integer = 0;
7603 }
7604 *dest = &p->subs[idx].f;
7605 } else if (p->callwaitcas) {
7606 if (f->frametype == AST_FRAME_DTMF_END) {
7607 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
7608 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
7609 ast_free(p->cidspill);
7610 p->cidspill = NULL;
7611 send_cwcidspill(p);
7612 }
7613 p->callwaitcas = 0;
7614 }
7615 p->subs[idx].f.frametype = AST_FRAME_NULL;
7616 p->subs[idx].f.subclass.integer = 0;
7617 *dest = &p->subs[idx].f;
7618 } else if (f->subclass.integer == 'f') {
7619 if (f->frametype == AST_FRAME_DTMF_END) {
7620 /* Fax tone -- Handle and return NULL */
7621 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
7622 /* If faxbuffers are configured, use them for the fax transmission */
7623 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
7624 struct dahdi_bufferinfo bi = {
7625 .txbufpolicy = p->faxbuf_policy,
7626 .bufsize = p->bufsize,
7627 .numbufs = p->faxbuf_no
7628 };
7629 int res;
7630
7631 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7632 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
7633 } else {
7634 p->bufferoverrideinuse = 1;
7635 }
7636 }
7637 p->faxhandled = 1;
7638 if (p->dsp) {
7639 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
7641 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
7642 }
7643 if (strcmp(ast_channel_exten(ast), "fax")) {
7644 const char *target_context = ast_channel_context(ast);
7645
7646 /*
7647 * We need to unlock 'ast' here because ast_exists_extension has the
7648 * potential to start autoservice on the channel. Such action is prone
7649 * to deadlock if the channel is locked.
7650 *
7651 * ast_async_goto() has its own restriction on not holding the
7652 * channel lock.
7653 */
7655 ast_channel_unlock(ast);
7656 if (ast_exists_extension(ast, target_context, "fax", 1,
7657 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
7658 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
7659 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
7660 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
7661 if (ast_async_goto(ast, target_context, "fax", 1))
7662 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
7663 } else {
7664 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
7665 }
7666 ast_channel_lock(ast);
7667 ast_mutex_lock(&p->lock);
7668 } else {
7669 ast_debug(1, "Already in a fax extension, not redirecting\n");
7670 }
7671 } else {
7672 ast_debug(1, "Fax already handled\n");
7673 }
7674 dahdi_confmute(p, 0);
7675 }
7676 p->subs[idx].f.frametype = AST_FRAME_NULL;
7677 p->subs[idx].f.subclass.integer = 0;
7678 *dest = &p->subs[idx].f;
7679 }
7680}
static int dahdi_confmute(struct dahdi_pvt *p, int muted)
Definition: chan_dahdi.c:5187
#define CALLPROGRESS_FAX
Definition: chan_dahdi.c:682
static int send_cwcidspill(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5265
const char * ast_channel_exten(const struct ast_channel *chan)
@ AST_FRAME_DTMF_END
@ AST_FRAME_DTMF_BEGIN
@ AST_FRAME_CONTROL
@ AST_CONTROL_ANSWER
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:6969
int faxbuf_policy
Definition: chan_dahdi.h:142
unsigned int confirmanswer
TRUE if to wait for a DTMF digit to confirm answer.
Definition: chan_dahdi.h:245
int callprogress
Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
Definition: chan_dahdi.h:651
int faxbuf_no
Definition: chan_dahdi.h:141
unsigned int faxhandled
TRUE if a fax tone has already been handled.
Definition: chan_dahdi.h:274
unsigned int usefaxbuffers
Definition: chan_dahdi.h:276

References ast_async_goto(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt(), 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, dahdi_pvt::callprogress, CALLPROGRESS_FAX, dahdi_pvt::callwaitcas, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_subchannel::dfd, dahdi_pvt::dsp, dahdi_pvt::dsp_features, errno, dahdi_subchannel::f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxhandled, ast_frame::frametype, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, NULL, pbx_builtin_setvar_helper(), S_COR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, and dahdi_pvt::usefaxbuffers.

Referenced by dahdi_handle_event(), and dahdi_read().

◆ dahdi_handle_event()

static struct ast_frame * dahdi_handle_event ( struct ast_channel ast)
static

Definition at line 7737 of file chan_dahdi.c.

7738{
7739 int res, x;
7740 int idx, mysig;
7741 char *c;
7742 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7743 pthread_t threadid;
7744 struct ast_channel *chan;
7745 struct ast_frame *f;
7746
7747 idx = dahdi_get_index(ast, p, 0);
7748 if (idx < 0) {
7749 return &ast_null_frame;
7750 }
7751 mysig = p->sig;
7752 if (p->outsigmod > -1)
7753 mysig = p->outsigmod;
7754 p->subs[idx].f.frametype = AST_FRAME_NULL;
7755 p->subs[idx].f.subclass.integer = 0;
7756 p->subs[idx].f.datalen = 0;
7757 p->subs[idx].f.samples = 0;
7758 p->subs[idx].f.mallocd = 0;
7759 p->subs[idx].f.offset = 0;
7760 p->subs[idx].f.src = "dahdi_handle_event";
7761 p->subs[idx].f.data.ptr = NULL;
7762 f = &p->subs[idx].f;
7763
7764 if (p->fake_event) {
7765 res = p->fake_event;
7766 p->fake_event = 0;
7767 } else
7768 res = dahdi_get_event(p->subs[idx].dfd);
7769
7770 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
7771
7772 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
7773 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
7774 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
7775#if defined(HAVE_PRI)
7777 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
7778 && p->pri
7779 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7780 /* absorb event */
7781 } else
7782#endif /* defined(HAVE_PRI) */
7783 {
7784 /* Unmute conference */
7785 dahdi_confmute(p, 0);
7787 p->subs[idx].f.subclass.integer = res & 0xff;
7788 dahdi_handle_dtmf(ast, idx, &f);
7789 }
7790 return f;
7791 }
7792
7793 if (res & DAHDI_EVENT_DTMFDOWN) {
7794 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
7795#if defined(HAVE_PRI)
7797 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
7798 && p->pri
7799 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7800 /* absorb event */
7801 } else
7802#endif /* defined(HAVE_PRI) */
7803 {
7804 /* Mute conference */
7805 dahdi_confmute(p, 1);
7807 p->subs[idx].f.subclass.integer = res & 0xff;
7808 dahdi_handle_dtmf(ast, idx, &f);
7809 }
7810 return &p->subs[idx].f;
7811 }
7812
7813 switch (res) {
7814 case DAHDI_EVENT_EC_DISABLED:
7815 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
7816 p->echocanon = 0;
7817 break;
7818#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7819 case DAHDI_EVENT_TX_CED_DETECTED:
7820 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
7821 break;
7822 case DAHDI_EVENT_RX_CED_DETECTED:
7823 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
7824 break;
7825 case DAHDI_EVENT_EC_NLP_DISABLED:
7826 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
7827 break;
7828 case DAHDI_EVENT_EC_NLP_ENABLED:
7829 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
7830 break;
7831#endif
7832 case DAHDI_EVENT_BITSCHANGED:
7833#ifdef HAVE_OPENR2
7834 if (p->sig != SIG_MFCR2) {
7835 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
7836 } else {
7837 ast_debug(1, "bits changed in chan %d\n", p->channel);
7838 openr2_chan_handle_cas(p->r2chan);
7839 }
7840#else
7841 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
7842#endif
7843 break;
7844 case DAHDI_EVENT_PULSE_START:
7845 /* Stop tone if there's a pulse start and the PBX isn't started */
7846 if (!ast_channel_pbx(ast))
7847 tone_zone_play_tone(p->subs[idx].dfd, -1);
7848 break;
7849 case DAHDI_EVENT_DIALCOMPLETE:
7850 /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
7851#if defined(HAVE_PRI)
7853 if (p->inalarm) {
7854 break;
7855 }
7856 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
7857 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",
7858 ast_channel_name(ast), strerror(errno));
7859 return NULL;
7860 }
7861 if (x) {
7862 /* Still dialing in DAHDI driver */
7863 break;
7864 }
7865 /*
7866 * The ast channel is locked and the private may be locked more
7867 * than once.
7868 */
7870 break;
7871 }
7872#endif /* defined(HAVE_PRI) */
7873#ifdef HAVE_OPENR2
7874 if ((p->sig & SIG_MFCR2) && p->r2chan && ast_channel_state(ast) != AST_STATE_UP) {
7875 /* we don't need to do anything for this event for R2 signaling
7876 if the call is being setup */
7877 break;
7878 }
7879#endif
7880 if (p->inalarm) break;
7881 if ((p->radio || (p->oprmode < 0))) break;
7882 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
7883 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
7884 return NULL;
7885 }
7886 if (!x) { /* if not still dialing in driver */
7887 dahdi_ec_enable(p);
7888 if (p->echobreak) {
7889 dahdi_train_ec(p);
7890 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
7891 p->dop.op = DAHDI_DIAL_OP_REPLACE;
7892 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
7893 p->echobreak = 0;
7894 } else {
7895 p->dialing = 0;
7896 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
7897 /* if thru with dialing after offhook */
7902 break;
7903 } else { /* if to state wait for offhook to dial rest */
7904 /* we now wait for off hook */
7906 }
7907 }
7909 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
7910 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
7911 } else if (p->confirmanswer || (!p->dialednone
7912 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
7913 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
7914 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
7915 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
7916 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
7917 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
7918 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
7919 || (mysig == SIG_SF_FEATB)))) {
7921 } else if (!p->answeronpolarityswitch) {
7925 /* If aops=0 and hops=1, this is necessary */
7927 } else {
7928 /* Start clean, so we can catch the change to REV polarity when party answers */
7930 }
7931 }
7932 }
7933 }
7934 break;
7935 case DAHDI_EVENT_ALARM:
7936 switch (p->sig) {
7937#if defined(HAVE_PRI)
7940 break;
7941#endif /* defined(HAVE_PRI) */
7942#if defined(HAVE_SS7)
7943 case SIG_SS7:
7945 break;
7946#endif /* defined(HAVE_SS7) */
7947 default:
7948 p->inalarm = 1;
7949 break;
7950 }
7951 res = get_alarms(p);
7952 handle_alarms(p, res);
7953#ifdef HAVE_PRI
7954 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
7955 /* fall through intentionally */
7956 } else {
7957 break;
7958 }
7959#endif
7960#if defined(HAVE_SS7)
7961 if (p->sig == SIG_SS7)
7962 break;
7963#endif /* defined(HAVE_SS7) */
7964#ifdef HAVE_OPENR2
7965 if (p->sig == SIG_MFCR2)
7966 break;
7967#endif
7968 case DAHDI_EVENT_ONHOOK:
7969 if (p->radio) {
7972 break;
7973 }
7974 if (p->oprmode < 0)
7975 {
7976 if (p->oprmode != -1) { /* Operator flash recall */
7977 ast_verb(4, "Operator mode enabled on channel %d, holding line for channel %d\n", p->channel, p->oprpeer->channel);
7978 break;
7979 }
7980 /* Otherwise, immediate recall */
7981 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
7982 {
7983 /* Make sure it starts ringing */
7984 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
7985 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
7987 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
7988 ast_verb(4, "Operator recall, channel %d ringing back channel %d\n", p->oprpeer->channel, p->channel);
7989 }
7990 break;
7991 }
7992 switch (p->sig) {
7993 case SIG_FXOLS:
7994 case SIG_FXOGS:
7995 case SIG_FXOKS:
7996 /* Check for some special conditions regarding call waiting */
7997 if (idx == SUB_REAL) {
7998 /* The normal line was hung up */
7999 if (p->subs[SUB_CALLWAIT].owner) {
8000 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
8002 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
8004#if 0
8005 p->subs[idx].needanswer = 0;
8006 p->subs[idx].needringing = 0;
8007#endif
8008 p->callwaitingrepeat = 0;
8009 p->cidcwexpire = 0;
8010 p->cid_suppress_expire = 0;
8011 p->owner = NULL;
8012 /* Don't start streaming audio yet if the incoming call isn't up yet */
8014 p->dialing = 1;
8016 } else if (p->subs[SUB_THREEWAY].owner) {
8017 unsigned int mssinceflash;
8018 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
8019 the private structure -- not especially easy or clean */
8021 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
8022 DLA_UNLOCK(&p->lock);
8024 /* We can grab ast and p in that order, without worry. We should make sure
8025 nothing seriously bad has happened though like some sort of bizarre double
8026 masquerade! */
8027 DLA_LOCK(&p->lock);
8028 if (p->owner != ast) {
8029 ast_log(LOG_WARNING, "This isn't good...\n");
8030 return NULL;
8031 }
8032 }
8033 if (!p->subs[SUB_THREEWAY].owner) {
8034 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
8035 return NULL;
8036 }
8037 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
8038 ast_debug(1, "Last flash was %u ms ago\n", mssinceflash);
8039 if (mssinceflash < MIN_MS_SINCE_FLASH) {
8040 /* It hasn't been long enough since the last flashook. This is probably a bounce on
8041 hanging up. Hangup both channels now */
8042 if (p->subs[SUB_THREEWAY].owner)
8045 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
8047 } else if ((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) {
8048 if (p->transfer) {
8049 /* In any case this isn't a threeway call anymore */
8050 p->subs[SUB_REAL].inthreeway = 0;
8052 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
8053 if (!p->transfertobusy && ast_channel_state(ast) == AST_STATE_BUSY) {
8055 /* Swap subs and dis-own channel */
8057 p->owner = NULL;
8058 /* Ring the phone */
8060 } else if (!attempt_transfer(p)) {
8061 /*
8062 * Transfer successful. Don't actually hang up at this point.
8063 * Let our channel legs of the calls die off as the transfer
8064 * percolates through the core.
8065 */
8066 break;
8067 }
8068 } else {
8070 if (p->subs[SUB_THREEWAY].owner)
8072 }
8073 } else {
8075 /* Swap subs and dis-own channel */
8077 p->owner = NULL;
8078 /* Ring the phone */
8080 }
8081 }
8082 } else {
8083 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
8084 }
8085 /* Fall through */
8086 default:
8088 return NULL;
8089 }
8090 break;
8091 case DAHDI_EVENT_RINGOFFHOOK:
8092 if (p->inalarm) break;
8093 if (p->oprmode < 0)
8094 {
8095 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
8096 {
8097 /* Make sure it stops ringing */
8098 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
8099 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
8101 ast_debug(1, "Operator recall by channel %d for channel %d complete\n", p->oprpeer->channel, p->channel);
8102 }
8103 break;
8104 }
8105 if (p->radio)
8106 {
8109 break;
8110 }
8111 /* for E911, its supposed to wait for offhook then dial
8112 the second half of the dial string */
8113 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK)) {
8114 c = strchr(p->dialdest, '/');
8115 if (c)
8116 c++;
8117 else
8118 c = p->dialdest;
8119
8120 if (*c) {
8121 int numchars = snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
8122 if (numchars >= sizeof(p->dop.dialstr)) {
8123 ast_log(LOG_WARNING, "Dial string '%s' truncated\n", c);
8124 }
8125 } else {
8126 ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
8127 }
8128
8129 if (strlen(p->dop.dialstr) > 4) {
8130 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
8131 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
8132 p->echorest[sizeof(p->echorest) - 1] = '\0';
8133 p->echobreak = 1;
8134 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
8135 } else
8136 p->echobreak = 0;
8137 if (dahdi_dial_str(p, p->dop.op, p->dop.dialstr)) {
8138 x = DAHDI_ONHOOK;
8139 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
8140 return NULL;
8141 }
8142 p->dialing = 1;
8143 return &p->subs[idx].f;
8144 }
8145 switch (p->sig) {
8146 case SIG_FXOLS:
8147 case SIG_FXOGS:
8148 case SIG_FXOKS:
8149 switch (ast_channel_state(ast)) {
8150 case AST_STATE_RINGING:
8151 dahdi_ec_enable(p);
8152 dahdi_train_ec(p);
8155 /* Make sure it stops ringing */
8156 p->subs[SUB_REAL].needringing = 0;
8157 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
8158 ast_debug(1, "channel %d answered\n", p->channel);
8159
8160 /* Cancel any running CallerID spill */
8161 ast_free(p->cidspill);
8162 p->cidspill = NULL;
8164
8165 p->dialing = 0;
8166 p->callwaitcas = 0;
8167 if (p->confirmanswer) {
8168 /* Ignore answer if "confirm answer" is enabled */
8169 p->subs[idx].f.frametype = AST_FRAME_NULL;
8170 p->subs[idx].f.subclass.integer = 0;
8171 } else if (!ast_strlen_zero(p->dop.dialstr)) {
8172 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
8173 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8174 if (res) {
8175 p->dop.dialstr[0] = '\0';
8176 return NULL;
8177 } else {
8178 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
8179 p->subs[idx].f.frametype = AST_FRAME_NULL;
8180 p->subs[idx].f.subclass.integer = 0;
8181 p->dialing = 1;
8182 }
8183 p->dop.dialstr[0] = '\0';
8185 } else
8187 return &p->subs[idx].f;
8188 case AST_STATE_DOWN:
8190 ast_channel_rings_set(ast, 1);
8193 ast_debug(1, "channel %d picked up\n", p->channel);
8194 return &p->subs[idx].f;
8195 case AST_STATE_UP:
8196 /* Make sure it stops ringing */
8197 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
8198 /* Okay -- probably call waiting*/
8200 p->subs[idx].needunhold = 1;
8201 break;
8202 case AST_STATE_RESERVED:
8203 /* Start up dialtone */
8204 if (has_voicemail(p))
8205 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
8206 else
8207 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
8208 break;
8209 default:
8210 ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast_channel_state(ast));
8211 }
8212 break;
8213 case SIG_FXSLS:
8214 case SIG_FXSGS:
8215 case SIG_FXSKS:
8216 if (ast_channel_state(ast) == AST_STATE_RING) {
8217 p->ringt = p->ringt_base;
8218 }
8219
8220 /* If we get a ring then we cannot be in
8221 * reversed polarity. So we reset to idle */
8222 ast_debug(1, "Setting IDLE polarity due "
8223 "to ring. Old polarity was %d\n",
8224 p->polarity);
8226
8227 /* Fall through */
8228 case SIG_EM:
8229 case SIG_EM_E1:
8230 case SIG_EMWINK:
8231 case SIG_FEATD:
8232 case SIG_FEATDMF:
8233 case SIG_FEATDMF_TA:
8234 case SIG_E911:
8235 case SIG_FGC_CAMA:
8236 case SIG_FGC_CAMAMF:
8237 case SIG_FEATB:
8238 case SIG_SF:
8239 case SIG_SFWINK:
8240 case SIG_SF_FEATD:
8241 case SIG_SF_FEATDMF:
8242 case SIG_SF_FEATB:
8246 ast_debug(1, "Ring detected\n");
8249 } else if (p->outgoing && ((ast_channel_state(ast) == AST_STATE_RINGING) || (ast_channel_state(ast) == AST_STATE_DIALING))) {
8250 ast_debug(1, "Line answered\n");
8251 if (p->confirmanswer) {
8252 p->subs[idx].f.frametype = AST_FRAME_NULL;
8253 p->subs[idx].f.subclass.integer = 0;
8254 } else {
8258 }
8259 } else if (ast_channel_state(ast) != AST_STATE_RING)
8260 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast_channel_state(ast), p->channel);
8261 break;
8262 default:
8263 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
8264 }
8265 break;
8266 case DAHDI_EVENT_RINGBEGIN:
8267 switch (p->sig) {
8268 case SIG_FXSLS:
8269 case SIG_FXSGS:
8270 case SIG_FXSKS:
8271 if (ast_channel_state(ast) == AST_STATE_RING) {
8272 p->ringt = p->ringt_base;
8273 }
8274 break;
8275 }
8276 break;
8277 case DAHDI_EVENT_RINGERON:
8278 break;
8279 case DAHDI_EVENT_NOALARM:
8280 switch (p->sig) {
8281#if defined(HAVE_PRI)
8284 break;
8285#endif /* defined(HAVE_PRI) */
8286#if defined(HAVE_SS7)
8287 case SIG_SS7:
8289 break;
8290#endif /* defined(HAVE_SS7) */
8291 default:
8292 p->inalarm = 0;
8293 break;
8294 }
8296 break;
8297 case DAHDI_EVENT_WINKFLASH:
8298 if (p->inalarm) break;
8299 if (p->radio) break;
8300 if (p->oprmode < 0) break;
8301 if (p->oprmode > 1)
8302 {
8303 struct dahdi_params par;
8304
8305 memset(&par, 0, sizeof(par));
8306 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
8307 {
8308 if (!par.rxisoffhook)
8309 {
8310 /* Make sure it stops ringing */
8311 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
8312 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
8313 save_conference(p);
8314 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
8315 ast_verb(4, "Operator flash recall, channel %d ringing back channel %d\n", p->oprpeer->channel, p->channel);
8316 }
8317 }
8318 break;
8319 }
8320 /* Remember last time we got a flash-hook */
8321 p->flashtime = ast_tvnow();
8322 switch (mysig) {
8323 case SIG_FXOLS:
8324 case SIG_FXOGS:
8325 case SIG_FXOKS:
8326 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
8328
8329 /* Cancel any running CallerID spill */
8330 ast_free(p->cidspill);
8331 p->cidspill = NULL;
8333 p->callwaitcas = 0;
8334
8335 if (idx != SUB_REAL) {
8336 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
8337 goto winkflashdone;
8338 }
8339
8340 if (p->subs[SUB_CALLWAIT].owner) {
8341 /* Swap to call-wait */
8343 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
8344 p->owner = p->subs[SUB_REAL].owner;
8345 ast_debug(1, "Making %s the new owner\n", ast_channel_name(p->owner));
8348 p->subs[SUB_REAL].needanswer = 1;
8349 }
8350 p->callwaitingrepeat = 0;
8351 p->cidcwexpire = 0;
8352 p->cid_suppress_expire = 0;
8353 /* Start music on hold if appropriate */
8354 if (!p->subs[SUB_CALLWAIT].inthreeway) {
8356 }
8357 p->subs[SUB_CALLWAIT].needhold = 1;
8359 p->subs[SUB_REAL].needunhold = 1;
8360 } else if (!p->subs[SUB_THREEWAY].owner) {
8361 if (!p->threewaycalling) {
8362 /* Just send a flash if no 3-way calling */
8363 p->subs[SUB_REAL].needflash = 1;
8364 goto winkflashdone;
8365 } else if (!check_for_conference(p)) {
8366 ast_callid callid = 0;
8367 int callid_created;
8368 char cid_num[256];
8369 char cid_name[256];
8370
8371 cid_num[0] = 0;
8372 cid_name[0] = 0;
8373 if (p->dahditrcallerid && p->owner) {
8377 sizeof(cid_num));
8378 }
8382 sizeof(cid_name));
8383 }
8384 }
8385 /* XXX This section needs much more error checking!!! XXX */
8386 /* Start a 3-way call if feasible */
8387 if (!((ast_channel_pbx(ast)) ||
8388 (ast_channel_state(ast) == AST_STATE_UP) ||
8389 (ast_channel_state(ast) == AST_STATE_RING))) {
8390 ast_debug(1, "Flash when call not up or ringing\n");
8391 goto winkflashdone;
8392 }
8393 if (alloc_sub(p, SUB_THREEWAY)) {
8394 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
8395 goto winkflashdone;
8396 }
8397 callid_created = ast_callid_threadstorage_auto(&callid);
8398 /*
8399 * Make new channel
8400 *
8401 * We cannot hold the p or ast locks while creating a new
8402 * channel.
8403 */
8405 ast_channel_unlock(ast);
8406 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL, NULL, callid);
8407 ast_channel_lock(ast);
8408 ast_mutex_lock(&p->lock);
8409 if (p->dahditrcallerid) {
8410 if (!p->origcid_num)
8412 if (!p->origcid_name)
8414 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
8415 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
8416 }
8417 /* Swap things around between the three-way and real call */
8419 /* Disable echo canceller for better dialing */
8421 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
8422 if (res)
8423 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
8424 p->owner = chan;
8425 if (!chan) {
8426 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
8427 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
8428 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
8429 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
8430 dahdi_ec_enable(p);
8431 ast_hangup(chan);
8432 } else {
8433 ast_verb(3, "Started three way call on channel %d\n", p->channel);
8434
8435 /* Start music on hold */
8437 p->subs[SUB_THREEWAY].needhold = 1;
8438 }
8439 ast_callid_threadstorage_auto_clean(callid, callid_created);
8440 }
8441 } else {
8442 /* Already have a 3 way call */
8443 if (p->subs[SUB_THREEWAY].inthreeway) {
8444 /* Call is already up, drop the last person */
8445 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
8446 /* If the primary call isn't answered yet, use it */
8448 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
8450 p->owner = p->subs[SUB_REAL].owner;
8451 }
8452 /* Drop the last call and stop the conference */
8453 ast_verb(3, "Dropping three-way call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
8455 p->subs[SUB_REAL].inthreeway = 0;
8457 } else {
8458 /* Lets see what we're up to */
8459 if (((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) &&
8461 int otherindex = SUB_THREEWAY;
8462
8463 ast_verb(3, "Building conference call with %s and %s\n",
8466 /* Put them in the threeway, and flip */
8468 p->subs[SUB_REAL].inthreeway = 1;
8469 if (ast_channel_state(ast) == AST_STATE_UP) {
8471 otherindex = SUB_REAL;
8472 }
8473 if (p->subs[otherindex].owner) {
8474 ast_queue_unhold(p->subs[otherindex].owner);
8475 }
8476 p->subs[otherindex].needunhold = 1;
8477 p->owner = p->subs[SUB_REAL].owner;
8478 } else {
8479 ast_verb(3, "Dumping incomplete call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
8482 p->owner = p->subs[SUB_REAL].owner;
8483 if (p->subs[SUB_REAL].owner) {
8485 }
8486 p->subs[SUB_REAL].needunhold = 1;
8487 dahdi_ec_enable(p);
8488 }
8489 }
8490 }
8491winkflashdone:
8493 break;
8494 case SIG_EM:
8495 case SIG_EM_E1:
8496 case SIG_FEATD:
8497 case SIG_SF:
8498 case SIG_SFWINK:
8499 case SIG_SF_FEATD:
8500 case SIG_FXSLS:
8501 case SIG_FXSGS:
8502 if (p->dialing)
8503 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
8504 else
8505 ast_debug(1, "Got wink in weird state %u on channel %d\n", ast_channel_state(ast), p->channel);
8506 break;
8507 case SIG_FEATDMF_TA:
8508 switch (p->whichwink) {
8509 case 0:
8510 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", ast_channel_caller(p->owner)->ani2,
8513 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
8517 break;
8518 case 1:
8519 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
8520 break;
8521 case 2:
8522 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
8523 return NULL;
8524 }
8525 p->whichwink++;
8526 /* Fall through */
8527 case SIG_FEATDMF:
8528 case SIG_E911:
8529 case SIG_FGC_CAMAMF:
8530 case SIG_FGC_CAMA:
8531 case SIG_FEATB:
8532 case SIG_SF_FEATDMF:
8533 case SIG_SF_FEATB:
8534 case SIG_EMWINK:
8535 /* FGD MF and EMWINK *Must* wait for wink */
8536 if (!ast_strlen_zero(p->dop.dialstr)) {
8537 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8538 if (res) {
8539 p->dop.dialstr[0] = '\0';
8540 return NULL;
8541 } else
8542 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8543 }
8544 p->dop.dialstr[0] = '\0';
8545 break;
8546 default:
8547 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
8548 }
8549 break;
8550 case DAHDI_EVENT_HOOKCOMPLETE:
8551 if (p->inalarm) break;
8552 if ((p->radio || (p->oprmode < 0))) break;
8553 if (p->waitingfordt.tv_sec) break;
8554 switch (mysig) {
8555 case SIG_FXSLS: /* only interesting for FXS */
8556 case SIG_FXSGS:
8557 case SIG_FXSKS:
8558 case SIG_EM:
8559 case SIG_EM_E1:
8560 case SIG_EMWINK:
8561 case SIG_FEATD:
8562 case SIG_SF:
8563 case SIG_SFWINK:
8564 case SIG_SF_FEATD:
8565 if (!ast_strlen_zero(p->dop.dialstr)) {
8566 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8567 if (res) {
8568 p->dop.dialstr[0] = '\0';
8569 return NULL;
8570 } else
8571 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8572 }
8573 p->dop.dialstr[0] = '\0';
8574 p->dop.op = DAHDI_DIAL_OP_REPLACE;
8575 break;
8576 case SIG_FEATDMF:
8577 case SIG_FEATDMF_TA:
8578 case SIG_E911:
8579 case SIG_FGC_CAMA:
8580 case SIG_FGC_CAMAMF:
8581 case SIG_FEATB:
8582 case SIG_SF_FEATDMF:
8583 case SIG_SF_FEATB:
8584 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
8585 break;
8586 default:
8587 break;
8588 }
8589 break;
8590 case DAHDI_EVENT_POLARITY:
8591 /*
8592 * If we get a Polarity Switch event, check to see
8593 * if we should change the polarity state and
8594 * mark the channel as UP or if this is an indication
8595 * of remote end disconnect.
8596 */
8597 if (p->polarity == POLARITY_IDLE) {
8599 if (p->answeronpolarityswitch &&
8602 ast_debug(1, "Answering on polarity switch!\n");
8604 if (p->hanguponpolarityswitch) {
8606 }
8607 } else
8608 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8609 }
8610 /* Removed else statement from here as it was preventing hangups from ever happening*/
8611 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
8612 if (p->hanguponpolarityswitch &&
8613 (p->polarityonanswerdelay > 0) &&
8614 (p->polarity == POLARITY_REV) &&
8616 /* Added log_debug information below to provide a better indication of what is going on */
8617 ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast_channel_state(ast), p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
8618
8620 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
8623 } else
8624 ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8625
8626 } else {
8628 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8629 }
8630 /* Added more log_debug information below to provide a better indication of what is going on */
8631 ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast_channel_state(ast), p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
8632 break;
8633 default:
8634 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
8635 }
8636 return &p->subs[idx].f;
8637}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define AST_CAUSE_NO_ANSWER
Definition: causes.h:109
static int restore_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5250
static void dahdi_train_ec(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4941
static int attempt_transfer(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7496
static void * analog_ss_thread(void *data)
Definition: chan_dahdi.c:9877
static void handle_clear_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:3784
static int check_for_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7529
static int has_voicemail(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5281
#define CALLPROGRESS_PROGRESS
Definition: chan_dahdi.c:679
static void handle_alarms(struct dahdi_pvt *p, int alms)
Definition: chan_dahdi.c:7715
static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
Definition: chan_dahdi.c:7582
static struct ast_channel * dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid)
Definition: chan_dahdi.c:9518
#define MIN_MS_SINCE_FLASH
Definition: chan_dahdi.c:803
#define ast_channel_trylock(chan)
Definition: channel.h:2924
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1166
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition: channel.c:1191
void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value)
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1148
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
@ AST_STATE_DIALING_OFFHOOK
Definition: channelstate.h:44
@ AST_CONTROL_RING
@ AST_CONTROL_OFFHOOK
@ AST_CONTROL_RADIO_UNKEY
@ AST_CONTROL_RADIO_KEY
struct ast_frame ast_null_frame
Definition: main/frame.c:79
void ast_callid_threadstorage_auto_clean(ast_callid callid, int callid_created)
Use in conjunction with ast_callid_threadstorage_auto. Cleans up the references and if the callid was...
Definition: logger.c:2366
unsigned int ast_callid
int ast_callid_threadstorage_auto(ast_callid *callid)
Checks thread storage for a callid and stores a reference if it exists. If not, then a new one will b...
Definition: logger.c:2344
#define DLA_LOCK(lock)
Definition: lock.h:492
#define DLA_UNLOCK(lock)
Definition: lock.h:490
#define CHANNEL_DEADLOCK_AVOIDANCE(chan)
Definition: lock.h:474
void sig_pri_chan_alarm_notify(struct sig_pri_chan *p, int noalarm)
@ SIG_PRI_CALL_LEVEL_PROCEEDING
Definition: sig_pri.h:143
#define DAHDI_OVERLAPDIAL_INCOMING
Definition: sig_pri.h:253
void sig_pri_dial_complete(struct sig_pri_chan *pvt, struct ast_channel *ast)
void sig_ss7_set_alarm(struct sig_ss7_chan *p, int in_alarm)
struct ast_party_id id
Caller party ID.
Definition: channel.h:420
int ani2
Automatic Number Identification 2 (Info Digits)
Definition: channel.h:433
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:427
struct ast_party_name name
Subscriber name.
Definition: channel.h:340
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:279
char * str
Subscriber name (Malloced)
Definition: channel.h:264
unsigned int dahditrcallerid
TRUE if we should use the callerid from incoming call on dahdi transfer.
Definition: chan_dahdi.h:408
int polarityonanswerdelay
Minimal time period (ms) between the answer polarity switch and hangup polarity switch.
Definition: chan_dahdi.h:727
struct dahdi_pvt * oprpeer
Definition: chan_dahdi.h:152
char * origcid_name
Definition: chan_dahdi.h:539
int whichwink
Definition: chan_dahdi.h:697
char * origcid_num
Definition: chan_dahdi.h:538
unsigned int answeronpolarityswitch
TRUE if we can use a polarity reversal to mark when an outgoing call is answered by the remote party.
Definition: chan_dahdi.h:184
unsigned int threewaycalling
TRUE if three way calling is enabled.
Definition: chan_dahdi.h:368
int echotraining
Echo training time. 0 = disabled.
Definition: chan_dahdi.h:634
struct timeval polaritydelaytv
Start delay time if polarityonanswerdelay is nonzero.
Definition: chan_dahdi.h:729
unsigned int echobreak
XXX BOOLEAN Purpose???
Definition: chan_dahdi.h:264
char echorest[20]
Filled with 'w'. XXX Purpose??
Definition: chan_dahdi.h:636
char finaldial[64]
Second part of SIG_FEATDMF_TA wink operation.
Definition: chan_dahdi.h:699
unsigned int transfertobusy
TRUE if allowed to flash-transfer to busy channels.
Definition: chan_dahdi.h:413
unsigned int pulsedial
TRUE if a pulsed digit was detected. (Pulse dial phone detected)
Definition: chan_dahdi.h:356
char mohsuggest[MAX_MUSICCLASS]
Suggested music-on-hold class for peer channel to use for calls.
Definition: chan_dahdi.h:517
unsigned int needringing
Definition: chan_dahdi.h:83
unsigned int needhold
Definition: chan_dahdi.h:88
unsigned int needflash
Definition: chan_dahdi.h:87
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:588

References alloc_sub(), analog_ss_thread(), ast_party_caller::ani, ast_party_caller::ani2, dahdi_pvt::answeronpolarityswitch, ast_callid_threadstorage_auto(), ast_callid_threadstorage_auto_clean(), AST_CAUSE_NO_ANSWER, ast_channel_caller(), ast_channel_lock, ast_channel_name(), ast_channel_pbx(), ast_channel_rings_set(), ast_channel_softhangup_internal_flag_add(), ast_channel_tech_pvt(), ast_channel_trylock, ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, ast_copy_string(), ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_null_frame, ast_pthread_create_detached, ast_queue_hangup_with_cause(), ast_queue_hold(), ast_queue_unhold(), 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(), c, 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, dahdi_pvt::cid_num, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_conf_update(), dahdi_confmute(), dahdi_dial_str(), dahdi_ec_disable(), dahdi_ec_enable(), 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, NULL, 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_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::radio, restore_conference(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_COR, 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(), dahdi_pvt::threewaycalling, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, unalloc_sub(), ast_party_name::valid, ast_party_number::valid, dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.

Referenced by __dahdi_exception().

◆ dahdi_hangup()

static int dahdi_hangup ( struct ast_channel ast)
static

Definition at line 6238 of file chan_dahdi.c.

6239{
6240 int res = 0;
6241 int idx,x;
6242 int law;
6243 /*static int restore_gains(struct dahdi_pvt *p);*/
6244 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6245 struct dahdi_params par;
6246
6247 ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
6248 if (!ast_channel_tech_pvt(ast)) {
6249 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
6250 return 0;
6251 }
6252
6253 ast_mutex_lock(&p->lock);
6254 p->exten[0] = '\0';
6255 /* Always use sig_analog hangup handling for operator mode */
6256 if (dahdi_analog_lib_handles(p->sig, p->radio, 0)) {
6257 p->oprmode = 0;
6258 dahdi_confmute(p, 0);
6259 restore_gains(p);
6260 p->ignoredtmf = 0;
6261 p->waitingfordt.tv_sec = 0;
6262
6263 res = analog_hangup(p->sig_pvt, ast);
6264 revert_fax_buffers(p, ast);
6265
6266 goto hangup_out;
6267 } else {
6268 p->cid_num[0] = '\0';
6269 p->cid_name[0] = '\0';
6270 p->cid_subaddr[0] = '\0';
6271 }
6272
6273#if defined(HAVE_PRI)
6275 x = 1;
6276 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6277
6278 dahdi_confmute(p, 0);
6279 p->muting = 0;
6280 restore_gains(p);
6281 if (p->dsp) {
6282 ast_dsp_free(p->dsp);
6283 p->dsp = NULL;
6284 }
6285 p->ignoredtmf = 0;
6286
6287 /* Real channel, do some fixup */
6288 p->subs[SUB_REAL].owner = NULL;
6289 p->subs[SUB_REAL].needbusy = 0;
6291
6292 p->owner = NULL;
6293 p->cid_tag[0] = '\0';
6294 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */
6295 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
6296 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
6297 p->outgoing = 0;
6298 p->digital = 0;
6299 p->faxhandled = 0;
6300 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
6301
6302 revert_fax_buffers(p, ast);
6303
6304 p->law = p->law_default;
6305 law = p->law_default;
6306 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6307 if (res < 0) {
6308 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
6309 p->channel, strerror(errno));
6310 }
6311
6312 sig_pri_hangup(p->sig_pvt, ast);
6313
6314 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6316
6317 x = 0;
6318 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
6319 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
6320
6321 p->rdnis[0] = '\0';
6323 reset_conf(p);
6324
6325 /* Restore data mode */
6326 x = 0;
6327 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6328
6329 if (num_restart_pending == 0) {
6331 }
6332 goto hangup_out;
6333 }
6334#endif /* defined(HAVE_PRI) */
6335
6336#if defined(HAVE_SS7)
6337 if (p->sig == SIG_SS7) {
6338 x = 1;
6339 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6340
6341 dahdi_confmute(p, 0);
6342 p->muting = 0;
6343 restore_gains(p);
6344 if (p->dsp) {
6345 ast_dsp_free(p->dsp);
6346 p->dsp = NULL;
6347 }
6348 p->ignoredtmf = 0;
6349
6350 /* Real channel, do some fixup */
6351 p->subs[SUB_REAL].owner = NULL;
6352 p->subs[SUB_REAL].needbusy = 0;
6354
6355 p->owner = NULL;
6356 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */
6357 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
6358 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
6359 p->outgoing = 0;
6360 p->digital = 0;
6361 p->faxhandled = 0;
6362 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
6363
6364 revert_fax_buffers(p, ast);
6365
6366 p->law = p->law_default;
6367 law = p->law_default;
6368 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6369 if (res < 0) {
6370 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
6371 p->channel, strerror(errno));
6372 }
6373
6374 sig_ss7_hangup(p->sig_pvt, ast);
6375
6376 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6378
6379 x = 0;
6380 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
6381 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
6382
6384 reset_conf(p);
6385
6386 /* Restore data mode */
6387 x = 0;
6388 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6389
6390 if (num_restart_pending == 0) {
6392 }
6393 goto hangup_out;
6394 }
6395#endif /* defined(HAVE_SS7) */
6396
6397 idx = dahdi_get_index(ast, p, 1);
6398
6399 dahdi_confmute(p, 0);
6400 p->muting = 0;
6401 restore_gains(p);
6402 if (p->origcid_num) {
6403 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
6405 p->origcid_num = NULL;
6406 }
6407 if (p->origcid_name) {
6408 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
6410 p->origcid_name = NULL;
6411 }
6412 if (p->dsp)
6414
6415 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
6416 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
6417 p->ignoredtmf = 0;
6418
6419 if (idx > -1) {
6420 /* Real channel, do some fixup */
6421 p->subs[idx].owner = NULL;
6422 p->subs[idx].needanswer = 0;
6423 p->subs[idx].needflash = 0;
6424 p->subs[idx].needringing = 0;
6425 p->subs[idx].needbusy = 0;
6426 p->subs[idx].needcongestion = 0;
6427 p->subs[idx].linear = 0;
6429 dahdi_setlinear(p->subs[idx].dfd, 0);
6430 if (idx == SUB_REAL) {
6431 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
6432 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
6433 if (p->subs[SUB_CALLWAIT].inthreeway) {
6434 /* We had flipped over to answer a callwait and now it's gone */
6435 ast_debug(1, "We were flipped over to the callwait, moving back and not owning.\n");
6436 /* Move to the call-wait, but un-own us until they flip back. */
6439 p->owner = NULL;
6440 } else {
6441 /* The three way hung up, but we still have a call wait */
6442 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
6445 if (p->subs[SUB_REAL].inthreeway) {
6446 /* This was part of a three way call. Immediately make way for
6447 another call */
6448 ast_debug(1, "Call was complete, setting owner to former third call\n");
6449 p->owner = p->subs[SUB_REAL].owner;
6450 } else {
6451 /* This call hasn't been completed yet... Set owner to NULL */
6452 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
6453 p->owner = NULL;
6454 }
6455 p->subs[SUB_REAL].inthreeway = 0;
6456 }
6457 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
6458 /* Move to the call-wait and switch back to them. */
6461 p->owner = p->subs[SUB_REAL].owner;
6463 p->subs[SUB_REAL].needanswer = 1;
6465 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
6468 if (p->subs[SUB_REAL].inthreeway) {
6469 /* This was part of a three way call. Immediately make way for
6470 another call */
6471 ast_debug(1, "Call was complete, setting owner to former third call\n");
6472 p->owner = p->subs[SUB_REAL].owner;
6473 } else {
6474 /* This call hasn't been completed yet... Set owner to NULL */
6475 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
6476 p->owner = NULL;
6477 }
6478 p->subs[SUB_REAL].inthreeway = 0;
6479 }
6480 } else if (idx == SUB_CALLWAIT) {
6481 /* Ditch the holding callwait call, and immediately make it availabe */
6482 if (p->subs[SUB_CALLWAIT].inthreeway) {
6483 /* This is actually part of a three way, placed on hold. Place the third part
6484 on music on hold now */
6485 if (p->subs[SUB_THREEWAY].owner) {
6487 }
6489 /* Make it the call wait now */
6492 } else
6494 } else if (idx == SUB_THREEWAY) {
6495 if (p->subs[SUB_CALLWAIT].inthreeway) {
6496 /* The other party of the three way call is currently in a call-wait state.
6497 Start music on hold for them, and take the main guy out of the third call */
6498 if (p->subs[SUB_CALLWAIT].owner) {
6500 }
6502 }
6503 p->subs[SUB_REAL].inthreeway = 0;
6504 /* If this was part of a three way call index, let us make
6505 another three way call */
6507 } else {
6508 /* This wasn't any sort of call, but how are we an index? */
6509 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
6510 }
6511 }
6512
6513 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
6514 p->owner = NULL;
6515 p->ringt = 0;
6516 p->distinctivering = 0;
6517 p->confirmanswer = 0;
6518 p->outgoing = 0;
6519 p->digital = 0;
6520 p->faxhandled = 0;
6521 p->pulsedial = 0;
6522 if (p->dsp) {
6523 ast_dsp_free(p->dsp);
6524 p->dsp = NULL;
6525 }
6526
6527 revert_fax_buffers(p, ast);
6528
6529 p->law = p->law_default;
6530 law = p->law_default;
6531 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6532 if (res < 0)
6533 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
6534 /* Perform low level hangup if no owner left */
6535#ifdef HAVE_OPENR2
6536 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
6537 ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
6538 /* If it's an incoming call, check the mfcr2_forced_release setting */
6539 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
6540 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
6541 } else {
6542 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
6543 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
6544 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
6545 : dahdi_ast_cause_to_r2_cause(ast_channel_hangupcause(ast));
6546 dahdi_r2_disconnect_call(p, r2cause);
6547 }
6548 } else if (p->mfcr2call) {
6549 ast_debug(1, "Clearing call request on channel %d\n", p->channel);
6550 /* since ast_request() was called but not ast_call() we have not yet dialed
6551 and the openr2 stack will not call on_call_end callback, we need to unset
6552 the mfcr2call flag and bump the monitor count so the monitor thread can take
6553 care of this channel events from now on */
6554 p->mfcr2call = 0;
6555 }
6556#endif
6557 switch (p->sig) {
6558 case SIG_SS7:
6559 case SIG_MFCR2:
6561 case 0:
6562 break;
6563 default:
6564 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6565 break;
6566 }
6567 if (res < 0) {
6568 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
6569 }
6570 switch (p->sig) {
6571 case SIG_FXOGS:
6572 case SIG_FXOLS:
6573 case SIG_FXOKS:
6574 memset(&par, 0, sizeof(par));
6575 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
6576 if (!res) {
6577 struct analog_pvt *analog_p = p->sig_pvt;
6578#if 0
6579 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
6580#endif
6581 /* If they're off hook, try playing congestion */
6582 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
6583 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6584 else
6585 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6586 analog_p->fxsoffhookstate = par.rxisoffhook;
6587 }
6588 break;
6589 case SIG_FXSGS:
6590 case SIG_FXSLS:
6591 case SIG_FXSKS:
6592 /* Make sure we're not made available for at least two seconds assuming
6593 we were actually used for an inbound or outbound call. */
6595 time(&p->guardtime);
6596 p->guardtime += 2;
6597 }
6598 break;
6599 default:
6600 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6601 break;
6602 }
6603 if (p->sig)
6605 x = 0;
6606 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
6607 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
6608 p->didtdd = 0;
6609 p->callwaitcas = 0;
6612 p->waitingfordt.tv_sec = 0;
6613 p->dialing = 0;
6614 p->rdnis[0] = '\0';
6616 reset_conf(p);
6617 /* Restore data mode */
6618 switch (p->sig) {
6620 case SIG_SS7:
6621 x = 0;
6622 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
6623 break;
6624 default:
6625 break;
6626 }
6627 if (num_restart_pending == 0)
6629 }
6630
6631 p->callwaitingrepeat = 0;
6632 p->cidcwexpire = 0;
6633 p->cid_suppress_expire = 0;
6634 p->oprmode = 0;
6635hangup_out:
6637 ast_free(p->cidspill);
6638 p->cidspill = NULL;
6639
6640 if (p->reoriginate && p->sig == SIG_FXOKS && dahdi_analog_lib_handles(p->sig, p->radio, 0)) {
6641 /* Automatic reorigination: if all calls towards a user have hung up,
6642 * give dial tone again, so user doesn't need to cycle the hook state manually. */
6643 if (my_is_off_hook(p) && !p->owner) {
6644 /* 2 important criteria: channel must be off-hook, with no calls remaining (no owner) */
6645 ast_debug(1, "Queuing reorigination for channel %d\n", p->channel);
6646 my_play_tone(p, SUB_REAL, -1); /* Stop any congestion tone that may be present. */
6647 /* Must wait for the loop disconnect to end.
6648 * Sadly, these definitions are in dahdi/kernel.h, not dahdi/user.h
6649 * Calling usleep on an active DAHDI channel is a no-no, but this is okay.
6650 */
6651 usleep(800000); /* DAHDI_KEWLTIME + DAHDI_AFTERKEWLTIME */
6652 /* If the line is still off-hook and ownerless, actually queue the reorigination.
6653 * do_monitor will actually go ahead and do it. */
6654 if (!p->owner && my_is_off_hook(p)) {
6655 p->doreoriginate = 1; /* Tell do_monitor to reoriginate this channel */
6656 /* Note, my_off_hook will fail if called before the loop disconnect has finished
6657 * (important for FXOKS signaled channels). This is because DAHDI will reject
6658 * DAHDI_OFFHOOK while the channel is in TXSTATE_KEWL or TXSTATE_AFTERKEWL,
6659 * so we have to wait for that to finish (see comment above).
6660 * do_monitor itself cannot block, so make the blocking usleep call
6661 * here in the channel thread instead.
6662 */
6663 my_off_hook(p); /* Now, go ahead and take the channel back off hook (sig_analog put it on hook) */
6664 } else {
6665 ast_debug(1, "Channel %d is no longer eligible for reorigination (went back on hook or became in use)\n", p->channel);
6666 }
6667 }
6668 }
6669
6671 ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
6672
6674 if (p->restartpending) {
6676 }
6677
6678 if (p->destroy) {
6679 destroy_channel(p, 0);
6680 }
6682
6684 return 0;
6685}
static int reset_conf(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4817
static int num_restart_pending
Definition: chan_dahdi.c:766
static int my_is_off_hook(void *pvt)
Definition: chan_dahdi.c:2712
static int restart_monitor(void)
Definition: chan_dahdi.c:12156
static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
Definition: chan_dahdi.c:2584
static int my_off_hook(void *pvt)
Definition: chan_dahdi.c:2771
static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
Definition: chan_dahdi.c:6216
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
int ast_channel_hangupcause(const struct ast_channel *chan)
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7422
#define AST_OPTION_TONE_VERIFY
#define AST_OPTION_TDD
#define AST_OPTION_AUDIO_MODE
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:1277
int sig_pri_hangup(struct sig_pri_chan *p, struct ast_channel *ast)
int sig_ss7_hangup(struct sig_ss7_chan *p, struct ast_channel *ast)
int fxsoffhookstate
Definition: sig_analog.h:282
unsigned int permcallwaiting
TRUE if busy extensions will hear the call-waiting tone and can use hook-flash to switch between call...
Definition: chan_dahdi.h:334
unsigned int doreoriginate
Internal flag for if we should actually process a reorigination.
Definition: chan_dahdi.h:293
unsigned int permhidecallerid
TRUE if the outgoing caller ID is blocked/restricted/hidden.
Definition: chan_dahdi.h:339
unsigned int restartpending
Definition: chan_dahdi.h:357
int distinctivering
Definition: chan_dahdi.h:719
time_t guardtime
Definition: chan_dahdi.h:587
char rdnis[AST_MAX_EXTENSION]
Redirecting Directory Number Information Service (RDNIS) number.
Definition: chan_dahdi.h:545
int law_default
Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
Definition: chan_dahdi.h:554
unsigned int didtdd
Definition: chan_dahdi.h:251
unsigned int destroy
TRUE if the channel is to be destroyed on hangup. (Used by pseudo channels.)
Definition: chan_dahdi.h:250
unsigned int reoriginate
TRUE if FXS (FXO-signalled) channel should reoriginate for user to make a new call.
Definition: chan_dahdi.h:289
int muting
TRUE if confrence is muted.
Definition: chan_dahdi.h:763
char cid_tag[AST_MAX_EXTENSION]
Caller ID tag from incoming call.
Definition: chan_dahdi.h:531
unsigned int needcongestion
Definition: chan_dahdi.h:85

References analog_hangup(), ast_channel_hangupcause(), ast_channel_name(), ast_channel_setoption(), ast_channel_tech_pvt(), ast_channel_tech_pvt_set(), 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_hold(), ast_queue_unhold(), AST_STATE_RESERVED, AST_STATE_UP, 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_analog_lib_handles(), dahdi_conf_update(), dahdi_confmute(), dahdi_ec_disable(), 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::doreoriginate, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, analog_pvt::fxsoffhookstate, dahdi_pvt::guardtime, 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, my_is_off_hook(), my_off_hook(), my_play_tone(), dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, NULL, num_restart_pending, dahdi_pvt::oprmode, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_subchannel::owner, dahdi_pvt::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, dahdi_pvt::reoriginate, reset_conf(), restart_monitor(), dahdi_pvt::restartpending, restore_gains(), revert_fax_buffers(), dahdi_pvt::ringt, ast_module_info::self, 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(), unalloc_sub(), and dahdi_pvt::waitingfordt.

◆ dahdi_iflist_extract()

static void dahdi_iflist_extract ( struct dahdi_pvt pvt)
static

Definition at line 5588 of file chan_dahdi.c.

5589{
5590 /* Extract from the forward chain. */
5591 if (pvt->prev) {
5592 pvt->prev->next = pvt->next;
5593 } else if (iflist == pvt) {
5594 /* Node is at the head of the list. */
5595 iflist = pvt->next;
5596 }
5597
5598 /* Extract from the reverse chain. */
5599 if (pvt->next) {
5600 pvt->next->prev = pvt->prev;
5601 } else if (ifend == pvt) {
5602 /* Node is at the end of the list. */
5603 ifend = pvt->prev;
5604 }
5605
5606 /* Node is no longer in the list. */
5608 pvt->prev = NULL;
5609 pvt->next = NULL;
5610}
@ DAHDI_IFLIST_NONE
Definition: chan_dahdi.h:117
enum DAHDI_IFLIST which_iflist
Definition: chan_dahdi.h:168

References DAHDI_IFLIST_NONE, ifend, iflist, dahdi_pvt::next, NULL, dahdi_pvt::prev, and dahdi_pvt::which_iflist.

Referenced by destroy_dahdi_pvt().

◆ dahdi_iflist_insert()

static void dahdi_iflist_insert ( struct dahdi_pvt pvt)
static

Definition at line 5540 of file chan_dahdi.c.

5541{
5542 struct dahdi_pvt *cur;
5543
5545
5546 /* Find place in middle of list for the new interface. */
5547 for (cur = iflist; cur; cur = cur->next) {
5548 if (pvt->channel < cur->channel) {
5549 /* New interface goes before the current interface. */
5550 pvt->prev = cur->prev;
5551 pvt->next = cur;
5552 if (cur->prev) {
5553 /* Insert into the middle of the list. */
5554 cur->prev->next = pvt;
5555 } else {
5556 /* Insert at head of list. */
5557 iflist = pvt;
5558 }
5559 cur->prev = pvt;
5560 return;
5561 }
5562 }
5563
5564 /* New interface goes onto the end of the list */
5565 pvt->prev = ifend;
5566 pvt->next = NULL;
5567 if (ifend) {
5568 ifend->next = pvt;
5569 }
5570 ifend = pvt;
5571 if (!iflist) {
5572 /* List was empty */
5573 iflist = pvt;
5574 }
5575}
@ DAHDI_IFLIST_MAIN
Definition: chan_dahdi.h:118

References dahdi_pvt::channel, DAHDI_IFLIST_MAIN, ifend, iflist, dahdi_pvt::next, NULL, dahdi_pvt::prev, and dahdi_pvt::which_iflist.

Referenced by duplicate_pseudo(), and mkintf().

◆ dahdi_indicate()

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

Definition at line 9340 of file chan_dahdi.c.

9341{
9342 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9343 int res=-1;
9344 int idx;
9345 int func = DAHDI_FLASH;
9346
9347 ast_mutex_lock(&p->lock);
9348 ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
9349 switch (p->sig) {
9350#if defined(HAVE_PRI)
9352 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
9354 return res;
9355#endif /* defined(HAVE_PRI) */
9356#if defined(HAVE_SS7)
9357 case SIG_SS7:
9358 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
9360 return res;
9361#endif /* defined(HAVE_SS7) */
9362 default:
9363 break;
9364 }
9365#ifdef HAVE_OPENR2
9366 if (p->mfcr2 && !p->mfcr2_call_accepted) {
9368 /* if this is an R2 call and the call is not yet accepted, we don't want the
9369 tone indications to mess up with the MF tones */
9370 return 0;
9371 }
9372#endif
9373 idx = dahdi_get_index(chan, p, 0);
9374 if (idx == SUB_REAL) {
9375 switch (condition) {
9376 case AST_CONTROL_BUSY:
9377 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
9378 break;
9380 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
9381
9382 if (ast_channel_state(chan) != AST_STATE_UP) {
9383 if ((ast_channel_state(chan) != AST_STATE_RING) ||
9384 ((p->sig != SIG_FXSKS) &&
9385 (p->sig != SIG_FXSLS) &&
9386 (p->sig != SIG_FXSGS)))
9388 }
9389 break;
9391 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
9392 /* act as a progress or proceeding, allowing the caller to enter additional numbers */
9393 res = 0;
9394 break;
9396 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
9397 /* don't continue in ast_indicate */
9398 res = 0;
9399 break;
9401 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
9402 /* don't continue in ast_indicate */
9403 res = 0;
9404 break;
9406 /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
9407 switch (ast_channel_hangupcause(chan)) {
9410 case 0:/* Cause has not been set. */
9411 /* Supply a more appropriate cause. */
9413 break;
9414 default:
9415 break;
9416 }
9417 break;
9418 case AST_CONTROL_HOLD:
9419 ast_moh_start(chan, data, p->mohinterpret);
9420 break;
9421 case AST_CONTROL_UNHOLD:
9422 ast_moh_stop(chan);
9423 break;
9425 if (p->radio)
9426 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
9427 res = 0;
9428 break;
9430 if (p->radio)
9431 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
9432 res = 0;
9433 break;
9434 case AST_CONTROL_FLASH:
9435 /* flash hookswitch */
9436 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
9437 /* Clear out the dial buffer */
9438 p->dop.dialstr[0] = '\0';
9439 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
9440 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
9441 ast_channel_name(chan), strerror(errno));
9442 } else
9443 res = 0;
9444 } else
9445 res = 0;
9446 break;
9448 res = 0;
9449 break;
9450 case -1:
9451 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9452 break;
9453 }
9454 } else {
9455 res = 0;
9456 }
9458 return res;
9459}
#define AST_CAUSE_CONGESTION
Definition: causes.h:153
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:106
#define AST_CAUSE_USER_BUSY
Definition: causes.h:107
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
@ AST_CONTROL_SRCUPDATE
@ AST_CONTROL_PROGRESS
@ AST_CONTROL_BUSY
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_PROCEEDING
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_HOLD
@ AST_CONTROL_FLASH
@ AST_CONTROL_INCOMPLETE
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:7766
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7776
int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
char mohinterpret[MAX_MUSICCLASS]
The configured music-on-hold class to use for calls.
Definition: chan_dahdi.h:512

References AST_CAUSE_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_USER_BUSY, ast_channel_hangupcause(), ast_channel_hangupcause_set(), ast_channel_name(), ast_channel_tech_pvt(), 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, 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, and dahdi_pvt::subs.

Referenced by dahdi_fixup().

◆ dahdi_lock_sub_owner()

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

Definition at line 3712 of file chan_dahdi.c.

3713{
3714 for (;;) {
3715 if (!pvt->subs[sub_idx].owner) {
3716 /* No subchannel owner pointer */
3717 break;
3718 }
3719 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
3720 /* Got subchannel owner lock */
3721 break;
3722 }
3723 /* We must unlock the private to avoid the possibility of a deadlock */
3724 DEADLOCK_AVOIDANCE(&pvt->lock);
3725 }
3726}
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:479

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

Referenced by wakeup_sub().

◆ dahdi_master_slave_link()

void dahdi_master_slave_link ( struct dahdi_pvt slave,
struct dahdi_pvt master 
)

Definition at line 7388 of file chan_dahdi.c.

7389{
7390 int x;
7391 if (!slave || !master) {
7392 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
7393 return;
7394 }
7395 for (x = 0; x < MAX_SLAVES; x++) {
7396 if (!master->slaves[x]) {
7397 master->slaves[x] = slave;
7398 break;
7399 }
7400 }
7401 if (x >= MAX_SLAVES) {
7402 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
7403 master->slaves[MAX_SLAVES - 1] = slave;
7404 }
7405 if (slave->master)
7406 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
7407 slave->master = master;
7408
7409 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
7410}

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

Referenced by native_start().

◆ dahdi_master_slave_unlink()

void dahdi_master_slave_unlink ( struct dahdi_pvt slave,
struct dahdi_pvt master,
int  needlock 
)

Definition at line 7332 of file chan_dahdi.c.

7333{
7334 /* Unlink a specific slave or all slaves/masters from a given master */
7335 int x;
7336 int hasslaves;
7337 if (!master)
7338 return;
7339 if (needlock) {
7340 ast_mutex_lock(&master->lock);
7341 if (slave) {
7342 while (ast_mutex_trylock(&slave->lock)) {
7343 DEADLOCK_AVOIDANCE(&master->lock);
7344 }
7345 }
7346 }
7347 hasslaves = 0;
7348 for (x = 0; x < MAX_SLAVES; x++) {
7349 if (master->slaves[x]) {
7350 if (!slave || (master->slaves[x] == slave)) {
7351 /* Take slave out of the conference */
7352 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
7353 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
7354 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
7355 master->slaves[x]->master = NULL;
7356 master->slaves[x] = NULL;
7357 } else
7358 hasslaves = 1;
7359 }
7360 if (!hasslaves)
7361 master->inconference = 0;
7362 }
7363 if (!slave) {
7364 if (master->master) {
7365 /* Take master out of the conference */
7366 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
7367 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
7368 hasslaves = 0;
7369 for (x = 0; x < MAX_SLAVES; x++) {
7370 if (master->master->slaves[x] == master)
7371 master->master->slaves[x] = NULL;
7372 else if (master->master->slaves[x])
7373 hasslaves = 1;
7374 }
7375 if (!hasslaves)
7376 master->master->inconference = 0;
7377 }
7378 master->master = NULL;
7379 }
7380 dahdi_conf_update(master);
7381 if (needlock) {
7382 if (slave)
7383 ast_mutex_unlock(&slave->lock);
7384 ast_mutex_unlock(&master->lock);
7385 }
7386}
#define ast_mutex_trylock(a)
Definition: lock.h:191

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

Referenced by dahdi_fixup(), and native_stop().

◆ dahdi_new()

static struct ast_channel * dahdi_new ( struct dahdi_pvt i,
int  state,
int  startpbx,
int  idx,
int  law,
const struct ast_assigned_ids assignedids,
const struct ast_channel requestor,
ast_callid  callid 
)
static

Definition at line 9518 of file chan_dahdi.c.

9519{
9520 struct ast_channel *tmp;
9521 struct ast_format_cap *caps;
9522 struct ast_format *deflaw;
9523 int x;
9524 int features;
9525 struct ast_str *chan_name;
9526 struct ast_variable *v;
9527 char *dashptr;
9528 char device_name[AST_CHANNEL_NAME];
9529
9530 if (i->subs[idx].owner) {
9531 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
9532 return NULL;
9533 }
9534
9535#if defined(HAVE_PRI)
9536 /*
9537 * The dnid has been stuffed with the called-number[:subaddress]
9538 * by dahdi_request() for outgoing calls.
9539 */
9540 chan_name = create_channel_name(i, i->outgoing, i->dnid);
9541#else
9542 chan_name = create_channel_name(i);
9543#endif /* defined(HAVE_PRI) */
9544 if (!chan_name) {
9545 return NULL;
9546 }
9547
9549 if (!caps) {
9550 ast_free(chan_name);
9551 return NULL;
9552 }
9553
9554 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
9555 ast_free(chan_name);
9556 if (!tmp) {
9557 ao2_ref(caps, -1);
9558 return NULL;
9559 }
9560
9562
9563 if (callid) {
9564 ast_channel_callid_set(tmp, callid);
9565 }
9566
9568#if defined(HAVE_PRI)
9569 if (i->pri) {
9571 }
9572#endif /* defined(HAVE_PRI) */
9574 if (law) {
9575 i->law = law;
9576 if (law == DAHDI_LAW_ALAW) {
9577 deflaw = ast_format_alaw;
9578 } else {
9579 deflaw = ast_format_ulaw;
9580 }
9581 } else {
9582 switch (i->sig) {
9584 /* Make sure companding law is known. */
9585 i->law = (i->law_default == DAHDI_LAW_ALAW)
9586 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
9587 break;
9588 default:
9589 i->law = i->law_default;
9590 break;
9591 }
9592 if (i->law_default == DAHDI_LAW_ALAW) {
9593 deflaw = ast_format_alaw;
9594 } else {
9595 deflaw = ast_format_ulaw;
9596 }
9597 }
9598 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
9599 ast_format_cap_append(caps, deflaw, 0);
9601 ao2_ref(caps, -1);
9602 /* Start out assuming ulaw since it's smaller :) */
9607 i->subs[idx].linear = 0;
9608 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
9609 features = 0;
9610 if (idx == SUB_REAL) {
9611 if (i->busydetect && CANBUSYDETECT(i))
9612 features |= DSP_FEATURE_BUSY_DETECT;
9614 features |= DSP_FEATURE_CALL_PROGRESS;
9616 features |= DSP_FEATURE_WAITDIALTONE;
9617 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
9619 features |= DSP_FEATURE_FAX_DETECT;
9620 }
9621 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
9622 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
9623 i->hardwaredtmf = 0;
9624 features |= DSP_FEATURE_DIGIT_DETECT;
9625 } else if (NEED_MFDETECT(i)) {
9626 i->hardwaredtmf = 1;
9627 features |= DSP_FEATURE_DIGIT_DETECT;
9628 }
9629 }
9630 if (features) {
9631 if (i->dsp) {
9632 ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
9633 } else {
9634 if (i->channel != CHAN_PSEUDO)
9635 i->dsp = ast_dsp_new();
9636 else
9637 i->dsp = NULL;
9638 if (i->dsp) {
9639 i->dsp_features = features;
9640#if defined(HAVE_PRI) || defined(HAVE_SS7)
9641 /* We cannot do progress detection until receive PROGRESS message */
9642 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
9643 /* Remember requested DSP features, don't treat
9644 talking as ANSWER */
9645 i->dsp_features = features & ~DSP_PROGRESS_TALK;
9646 features = 0;
9647 }
9648#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9649 ast_dsp_set_features(i->dsp, features);
9653 if (i->busydetect && CANBUSYDETECT(i)) {
9656 }
9657 }
9658 }
9659 }
9660
9662
9663 if (state == AST_STATE_RING)
9666 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
9667 /* Only FXO signalled stuff can be picked up */
9672 }
9673 if (!ast_strlen_zero(i->parkinglot))
9674 ast_channel_parkinglot_set(tmp, i->parkinglot);
9675 if (!ast_strlen_zero(i->language))
9676 ast_channel_language_set(tmp, i->language);
9677 if (!i->owner)
9678 i->owner = tmp;
9680 ast_channel_accountcode_set(tmp, i->accountcode);
9681 if (i->amaflags)
9683 i->subs[idx].owner = tmp;
9685 if (!dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
9686 ast_channel_call_forward_set(tmp, i->call_forward);
9687 }
9688 /* If we've been told "no ADSI" then enforce it */
9689 if (!i->adsi)
9691 if (!ast_strlen_zero(i->exten))
9693 if (!ast_strlen_zero(i->rdnis)) {
9696 }
9697 if (!ast_strlen_zero(i->dnid)) {
9699 }
9700
9701 /* Don't use ast_set_callerid() here because it will
9702 * generate a needless NewCallerID event */
9703#if defined(HAVE_PRI) || defined(HAVE_SS7)
9704 if (!ast_strlen_zero(i->cid_ani)) {
9707 } else if (!ast_strlen_zero(i->cid_num)) {
9710 }
9711#else
9712 if (!ast_strlen_zero(i->cid_num)) {
9715 }
9716#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9722 /* clear the fake event in case we posted one before we had ast_channel */
9723 i->fake_event = 0;
9724 /* Assure there is no confmute on this channel */
9725 dahdi_confmute(i, 0);
9726 i->muting = 0;
9727 /* Configure the new channel jb */
9729
9730 /* Set initial device state */
9731 ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
9732 dashptr = strrchr(device_name, '-');
9733 if (dashptr) {
9734 *dashptr = '\0';
9735 }
9738
9739 for (v = i->vars ; v ; v = v->next)
9741
9743
9745
9747
9749 if (startpbx) {
9750#ifdef HAVE_OPENR2
9751 if (i->mfcr2call) {
9752 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
9753 }
9754#endif
9755 if (ast_pbx_start(tmp)) {
9756 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
9757 ast_hangup(tmp);
9758 return NULL;
9759 }
9760 }
9761 return tmp;
9762}
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
Definition: abstract_jb.c:593
void ast_cc_copy_config_params(struct ast_cc_config_params *dest, const struct ast_cc_config_params *src)
copy CCSS configuration parameters from one structure to another
Definition: ccss.c:854
#define CALLPROGRESS_FAX_INCOMING
Definition: chan_dahdi.c:681
#define CALLPROGRESS_FAX_OUTGOING
Definition: chan_dahdi.c:680
static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
Definition: chan_dahdi.c:1956
static struct ast_jb_conf global_jbconf
Definition: chan_dahdi.c:626
static char progzone[10]
Definition: chan_dahdi.c:726
#define CANBUSYDETECT(p)
Definition: chan_dahdi.c:714
void ast_channel_named_pickupgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1258
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
int ast_channel_cc_params_init(struct ast_channel *chan, const struct ast_cc_config_params *base_params)
Set up datastore with CCSS parameters for a channel.
Definition: channel.c:10451
@ AST_ADSI_UNAVAILABLE
Definition: channel.h:871
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
void ast_channel_named_callgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2426
@ AST_FLAG_DISABLE_DEVSTATE_CACHE
Definition: channel.h:1029
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
@ AST_DEVSTATE_NOT_CACHABLE
Definition: devicestate.h:69
int ast_devstate_changed_literal(enum ast_device_state state, enum ast_devstate_cache cachable, const char *device)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:471
#define DSP_FEATURE_WAITDIALTONE
Definition: dsp.h:44
#define DSP_FEATURE_BUSY_DETECT
Definition: dsp.h:27
void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, const struct ast_dsp_busy_pattern *cadence)
Set expected lengths of the busy tone.
Definition: dsp.c:1804
#define DSP_FEATURE_FAX_DETECT
Definition: dsp.h:29
#define DSP_FEATURE_CALL_PROGRESS
Definition: dsp.h:43
void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
Set number of required cadences for busy.
Definition: dsp.c:1793
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1758
int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
Set zone for doing progress detection.
Definition: dsp.c:1892
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:443
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4708
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Definition of a media format.
Definition: format.c:43
struct ast_party_dialed::@208 number
Dialed/Called number.
char * str
Subscriber phone number (Malloced)
Definition: channel.h:386
char * tag
User-set "tag".
Definition: channel.h:354
int presentation
Q.931 encoded presentation-indicator encoded field.
Definition: channel.h:277
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:295
int plan
Q.931 Type-Of-Number and Numbering-Plan encoded fields.
Definition: channel.h:293
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:527
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
struct ast_variable * vars
Channel variable list with associated values to set when a channel is created.
Definition: chan_dahdi.h:584
int busycount
Number of times to see "busy" tone before hanging up.
Definition: chan_dahdi.h:641
int waitfordialtone
Number of milliseconds to wait for dialtone.
Definition: chan_dahdi.h:656
unsigned int adsi
TRUE if ADSI (Analog Display Services Interface) available.
Definition: chan_dahdi.h:178
int dialtone_scanning_time_elapsed
Definition: chan_dahdi.h:670
char dnid[AST_MAX_EXTENSION]
Dialed Number Identifier.
Definition: chan_dahdi.h:547
struct ast_namedgroups * named_pickupgroups
Named pickup groups this belongs to.
Definition: chan_dahdi.h:579
int cid_ani2
Automatic Number Identification code from PRI.
Definition: chan_dahdi.h:524
struct ast_namedgroups * named_callgroups
Named call groups this belongs to.
Definition: chan_dahdi.h:574
unsigned int busydetect
TRUE if busy detection is enabled. (Listens for the beep-beep busy pattern.)
Definition: chan_dahdi.h:206
ast_group_t pickupgroup
Bitmapped pickup groups this belongs to.
Definition: chan_dahdi.h:569
int callingpres
Definition: chan_dahdi.h:592
char parkinglot[AST_MAX_EXTENSION]
Definition: chan_dahdi.h:518
int amaflags
Definition: chan_dahdi.h:701
char language[MAX_LANGUAGE]
Language configured for calls.
Definition: chan_dahdi.h:507
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_dahdi.h:700
struct ast_dsp_busy_pattern busy_cadence
Busy cadence pattern description.
Definition: chan_dahdi.h:646
ast_group_t callgroup
Bitmapped call groups this belongs to.
Definition: chan_dahdi.h:564
int dialtone_detect
Number of frames to watch for dialtone in incoming calls.
Definition: chan_dahdi.h:669
int cid_ton
Caller ID Q.931 TON/NPI field values. Set by PRI. Zero otherwise.
Definition: chan_dahdi.h:533

References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, ast_party_caller::ani, ast_party_caller::ani2, ao2_ref, AST_ADSI_UNAVAILABLE, ast_cc_copy_config_params(), ast_channel_adsicpe_set(), ast_channel_alloc, ast_channel_amaflags_set(), ast_channel_caller(), ast_channel_callgroup_set(), ast_channel_callid_set(), ast_channel_cc_params_init(), ast_channel_context_set(), ast_channel_dialed(), ast_channel_exten_set(), ast_channel_flags(), AST_CHANNEL_NAME, ast_channel_name(), ast_channel_named_callgroups_set(), ast_channel_named_pickupgroups_set(), ast_channel_nativeformats_set(), ast_channel_pickupgroup_set(), ast_channel_redirecting(), ast_channel_rings_set(), ast_channel_set_fd(), ast_channel_set_rawreadformat(), ast_channel_set_rawwriteformat(), ast_channel_set_readformat(), ast_channel_set_writeformat(), ast_channel_stage_snapshot(), ast_channel_stage_snapshot_done(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_unlock, ast_copy_string(), ast_debug, AST_DEVICE_UNKNOWN, ast_devstate_changed_literal(), AST_DEVSTATE_NOT_CACHABLE, ast_dsp_new(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_digitmode(), ast_dsp_set_features(), AST_FLAG_DISABLE_DEVSTATE_CACHE, ast_format_alaw, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_ulaw, ast_free, ast_hangup(), ast_jb_configure(), ast_log, ast_module_ref, ast_pbx_start(), ast_set_flag, 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, dahdi_pvt::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, dahdi_pvt::context, create_channel_name(), dahdi_ami_channel_event(), dahdi_analog_lib_handles(), dahdi_confmute(), dahdi_setlinear(), dahdi_sig_pri_lib_handles(), dahdi_tech, dahdi_subchannel::dfd, dahdi_pvt::dialtone_detect, dahdi_pvt::dialtone_scanning_time_elapsed, 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, dahdi_pvt::dtmfrelax, 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_party_id::name, ast_variable::name, dahdi_pvt::named_callgroups, dahdi_pvt::named_pickupgroups, NEED_MFDETECT, ast_variable::next, NULL, ast_party_id::number, ast_party_dialed::number, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::parkinglot, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_party_number::plan, ast_party_name::presentation, ast_party_number::presentation, progzone, dahdi_pvt::radio, dahdi_pvt::rdnis, ast_module_info::self, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_PRI_LIB_HANDLE_CASES, SIG_SS7, ast_party_number::str, ast_party_dialed::str, SUB_REAL, subnames, dahdi_pvt::subs, ast_party_id::tag, tmp(), ast_party_number::valid, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

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

◆ dahdi_new_callid_clean()

static struct ast_channel * dahdi_new_callid_clean ( struct dahdi_pvt i,
int  state,
int  startpbx,
int  idx,
int  law,
const struct ast_assigned_ids assignedids,
const struct ast_channel requestor,
ast_callid  callid,
int  callid_created 
)
static

Definition at line 9509 of file chan_dahdi.c.

9510{
9511 struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, assignedids, requestor, callid);
9512
9514
9515 return new_channel;
9516}

References ast_callid_threadstorage_auto_clean(), ast_channel::callid, and dahdi_new().

Referenced by my_new_analog_ast_channel().

◆ dahdi_open()

static int dahdi_open ( char *  fn)
static

Definition at line 4334 of file chan_dahdi.c.

4335{
4336 int fd;
4337 int isnum;
4338 int chan = 0;
4339 int bs;
4340 int x;
4341 isnum = 1;
4342 for (x = 0; x < strlen(fn); x++) {
4343 if (!isdigit(fn[x])) {
4344 isnum = 0;
4345 break;
4346 }
4347 }
4348 if (isnum) {
4349 chan = atoi(fn);
4350 if (chan < 1) {
4351 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
4352 return -1;
4353 }
4354 fn = "/dev/dahdi/channel";
4355 }
4356 fd = open(fn, O_RDWR | O_NONBLOCK);
4357 if (fd < 0) {
4358 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
4359 return -1;
4360 }
4361 if (chan) {
4362 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
4363 x = errno;
4364 close(fd);
4365 errno = x;
4366 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
4367 return -1;
4368 }
4369 }
4370 bs = READ_SIZE;
4371 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
4372 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
4373 x = errno;
4374 close(fd);
4375 errno = x;
4376 return -1;
4377 }
4378 return fd;
4379}
char * bs
Definition: eagi_proxy.c:73

References ast_log, bs, errno, LOG_WARNING, READ_SIZE, and ast_channel::x.

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

◆ dahdi_queryoption()

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

Definition at line 6782 of file chan_dahdi.c.

6783{
6784 char *cp;
6785 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
6786
6787 /* all supported options require data */
6788 if (!p || !data || (*datalen < 1)) {
6789 errno = EINVAL;
6790 return -1;
6791 }
6792
6793 switch (option) {
6794 case AST_OPTION_TDD:
6795 cp = (char *) data;
6796 if (p->mate) {
6797 *cp = 2;
6798 } else {
6799 *cp = p->tdd ? 1 : 0;
6800 }
6801 break;
6803 cp = (char *) data;
6804 *cp = p->ignoredtmf ? 0 : 1;
6805 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6806 break;
6808 cp = (char *) data;
6809 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
6810 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6811 break;
6813#if defined(HAVE_PRI)
6814#if defined(HAVE_PRI_CCSS)
6816 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
6817 break;
6818 }
6819#endif /* defined(HAVE_PRI_CCSS) */
6820#endif /* defined(HAVE_PRI) */
6821 return -1;
6822 default:
6823 return -1;
6824 }
6825
6826 errno = 0;
6827
6828 return 0;
6829}
#define AST_OPTION_DIGIT_DETECT
#define AST_OPTION_CC_AGENT_TYPE
#define AST_OPTION_FAX_DETECT
struct tdd_state * tdd
Definition: chan_dahdi.h:702
unsigned int mate
TRUE if TDD in MATE mode.
Definition: chan_dahdi.h:326

References ast_channel_name(), ast_channel_tech_pvt(), ast_copy_string(), ast_debug, AST_OPTION_CC_AGENT_TYPE, AST_OPTION_DIGIT_DETECT, AST_OPTION_FAX_DETECT, AST_OPTION_TDD, dahdi_sig_pri_lib_handles(), DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, errno, dahdi_pvt::ignoredtmf, dahdi_pvt::mate, dahdi_pvt::sig, and dahdi_pvt::tdd.

◆ dahdi_queue_frame()

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

Definition at line 3737 of file chan_dahdi.c.

3738{
3739 for (;;) {
3740 if (p->owner) {
3741 if (ast_channel_trylock(p->owner)) {
3743 } else {
3744 ast_queue_frame(p->owner, f);
3746 break;
3747 }
3748 } else
3749 break;
3750 }
3751}
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1139

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

Referenced by action_dahdidialoffhook().

◆ dahdi_read()

static struct ast_frame * dahdi_read ( struct ast_channel ast)
static

Definition at line 8776 of file chan_dahdi.c.

8777{
8778 struct dahdi_pvt *p;
8779 int res;
8780 int idx;
8781 void *readbuf;
8782 struct ast_frame *f;
8783
8784 /*
8785 * For analog channels, we must do deadlock avoidance because
8786 * analog ports can have more than one Asterisk channel using
8787 * the same private structure.
8788 */
8789 p = ast_channel_tech_pvt(ast);
8790 while (ast_mutex_trylock(&p->lock)) {
8792
8793 /*
8794 * Check to see if the channel is still associated with the same
8795 * private structure. While the Asterisk channel was unlocked
8796 * the following events may have occured:
8797 *
8798 * 1) A masquerade may have associated the channel with another
8799 * technology or private structure.
8800 *
8801 * 2) For PRI calls, call signaling could change the channel
8802 * association to another B channel (private structure).
8803 */
8804 if (ast_channel_tech_pvt(ast) != p) {
8805 /* The channel is no longer associated. Quit gracefully. */
8806 return &ast_null_frame;
8807 }
8808 }
8809
8810 idx = dahdi_get_index(ast, p, 0);
8811
8812 /* Hang up if we don't really exist */
8813 if (idx < 0) {
8814 ast_log(LOG_WARNING, "We don't exist?\n");
8816 return NULL;
8817 }
8818
8819 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
8821 return NULL;
8822 }
8823
8824 p->subs[idx].f.frametype = AST_FRAME_NULL;
8825 p->subs[idx].f.datalen = 0;
8826 p->subs[idx].f.samples = 0;
8827 p->subs[idx].f.mallocd = 0;
8828 p->subs[idx].f.offset = 0;
8829 p->subs[idx].f.subclass.integer = 0;
8830 p->subs[idx].f.delivery = ast_tv(0,0);
8831 p->subs[idx].f.src = "dahdi_read";
8832 p->subs[idx].f.data.ptr = NULL;
8833
8834 /* make sure it sends initial key state as first frame */
8835 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
8836 {
8837 struct dahdi_params ps;
8838
8839 memset(&ps, 0, sizeof(ps));
8840 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
8842 return NULL;
8843 }
8844 p->firstradio = 1;
8846 if (ps.rxisoffhook)
8847 {
8849 }
8850 else
8851 {
8853 }
8855 return &p->subs[idx].f;
8856 }
8857 if (p->ringt > 0) {
8858 if (!(--p->ringt)) {
8860 return NULL;
8861 }
8862 }
8863
8864#ifdef HAVE_OPENR2
8865 if (p->mfcr2) {
8866 openr2_chan_process_event(p->r2chan);
8867 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
8869 /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
8870 * now enqueue a progress frame to bridge the media up */
8871 if (p->mfcr2_call_accepted &&
8872 !p->mfcr2_progress_sent &&
8874 ast_debug(1, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
8875 ast_queue_frame(p->owner, &fr);
8876 p->mfcr2_progress_sent = 1;
8877 }
8878 }
8879 }
8880#endif
8881
8882 if (p->subs[idx].needringing) {
8883 /* Send ringing frame if requested */
8884 p->subs[idx].needringing = 0;
8889 return &p->subs[idx].f;
8890 }
8891
8892 if (p->subs[idx].needbusy) {
8893 /* Send busy frame if requested */
8894 p->subs[idx].needbusy = 0;
8898 return &p->subs[idx].f;
8899 }
8900
8901 if (p->subs[idx].needcongestion) {
8902 /* Send congestion frame if requested */
8903 p->subs[idx].needcongestion = 0;
8907 return &p->subs[idx].f;
8908 }
8909
8910 if (p->subs[idx].needanswer) {
8911 /* Send answer frame if requested */
8912 p->subs[idx].needanswer = 0;
8916 return &p->subs[idx].f;
8917 }
8918#ifdef HAVE_OPENR2
8919 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
8920 /* openr2 took care of reading and handling any event
8921 (needanswer, needbusy etc), if we continue we will read()
8922 twice, lets just return a null frame. This should only
8923 happen when openr2 is dialing out */
8925 return &ast_null_frame;
8926 }
8927#endif
8928
8929 if (p->subs[idx].needflash) {
8930 /* Send answer frame if requested */
8931 p->subs[idx].needflash = 0;
8935 return &p->subs[idx].f;
8936 }
8937
8938 if (p->subs[idx].needhold) {
8939 /* Send answer frame if requested */
8940 p->subs[idx].needhold = 0;
8944 ast_debug(1, "Sending hold on '%s'\n", ast_channel_name(ast));
8945 return &p->subs[idx].f;
8946 }
8947
8948 if (p->subs[idx].needunhold) {
8949 /* Send answer frame if requested */
8950 p->subs[idx].needunhold = 0;
8954 ast_debug(1, "Sending unhold on '%s'\n", ast_channel_name(ast));
8955 return &p->subs[idx].f;
8956 }
8957
8958 /*
8959 * If we have a fake_event, fake an exception to handle it only
8960 * if this channel owns the private.
8961 */
8962 if (p->fake_event && p->owner == ast) {
8963 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8964 struct analog_pvt *analog_p = p->sig_pvt;
8965
8966 f = analog_exception(analog_p, ast);
8967 } else {
8968 f = __dahdi_exception(ast);
8969 }
8971 return f;
8972 }
8973
8975 if (!p->subs[idx].linear) {
8976 p->subs[idx].linear = 1;
8977 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8978 if (res)
8979 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
8980 }
8981 } else {
8982 if (p->subs[idx].linear) {
8983 p->subs[idx].linear = 0;
8984 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8985 if (res)
8986 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
8987 }
8988 }
8989 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
8990 CHECK_BLOCKING(ast);
8991 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
8993 /* Check for hangup */
8994 if (res < 0) {
8995 f = NULL;
8996 if (res == -1) {
8997 if (errno == EAGAIN) {
8998 /* Return "NULL" frame if there is nobody there */
9000 return &p->subs[idx].f;
9001 } else if (errno == ELAST) {
9002 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9003 struct analog_pvt *analog_p = p->sig_pvt;
9004 f = analog_exception(analog_p, ast);
9005 } else {
9006 f = __dahdi_exception(ast);
9007 }
9008 } else
9009 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
9010 }
9012 return f;
9013 }
9014 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
9015 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
9016 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9017 struct analog_pvt *analog_p = p->sig_pvt;
9018 f = analog_exception(analog_p, ast);
9019 } else {
9020 f = __dahdi_exception(ast);
9021 }
9023 return f;
9024 }
9025 if (p->tdd) { /* if in TDD mode, see if we receive that */
9026 int c;
9027
9028 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
9029 if (c < 0) {
9030 ast_debug(1,"tdd_feed failed\n");
9032 return NULL;
9033 }
9034 if (c) { /* if a char to return */
9035 p->subs[idx].f.subclass.integer = 0;
9036 p->subs[idx].f.frametype = AST_FRAME_TEXT;
9037 p->subs[idx].f.mallocd = 0;
9038 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
9039 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
9040 p->subs[idx].f.datalen = 1;
9041 *((char *) p->subs[idx].f.data.ptr) = c;
9043 return &p->subs[idx].f;
9044 }
9045 }
9046 if (idx == SUB_REAL) {
9047 /* Ensure the CW timers decrement only on a single subchannel */
9048 if (p->cidcwexpire) {
9049 if (!--p->cidcwexpire) {
9050 /* Expired CID/CW */
9051 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
9053 }
9054 }
9055 if (p->cid_suppress_expire) {
9057 }
9058 if (p->callwaitingrepeat) {
9059 if (!--p->callwaitingrepeat) {
9060 /* Expired, Repeat callwaiting tone */
9061 ++p->callwaitrings;
9062 dahdi_callwait(ast);
9063 }
9064 }
9065 }
9066 if (p->subs[idx].linear) {
9067 p->subs[idx].f.datalen = READ_SIZE * 2;
9068 } else
9069 p->subs[idx].f.datalen = READ_SIZE;
9070
9071 /* Handle CallerID Transmission */
9072 if ((p->owner == ast) && p->cidspill) {
9073 send_callerid(p);
9074 }
9075
9076 p->subs[idx].f.frametype = AST_FRAME_VOICE;
9078 p->subs[idx].f.samples = READ_SIZE;
9079 p->subs[idx].f.mallocd = 0;
9080 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
9081 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
9082#if 0
9083 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
9084#endif
9085 if ((p->dialing && !p->waitingfordt.tv_sec) || p->radio || /* Transmitting something */
9086 (idx && (ast_channel_state(ast) != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
9087 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
9088 ) {
9089 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
9090 don't send anything */
9091 p->subs[idx].f.frametype = AST_FRAME_NULL;
9092 p->subs[idx].f.subclass.integer = 0;
9093 p->subs[idx].f.samples = 0;
9094 p->subs[idx].f.mallocd = 0;
9095 p->subs[idx].f.offset = 0;
9096 p->subs[idx].f.data.ptr = NULL;
9097 p->subs[idx].f.datalen= 0;
9098 }
9099 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec || p->dialtone_detect) && !idx) {
9100 /* Perform busy detection etc on the dahdi line */
9101 int mute;
9102
9104 && p->faxdetect_timeout
9106 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
9108 ast_debug(1, "Channel driver fax CNG detection timeout on %s\n",
9109 ast_channel_name(ast));
9110 }
9111
9112 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
9113
9114 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
9115 mute = ast_dsp_was_muted(p->dsp);
9116 if (p->muting != mute) {
9117 p->muting = mute;
9118 dahdi_confmute(p, mute);
9119 }
9120
9121 if (f) {
9123 && !p->outgoing && ast_channel_state(ast) == AST_STATE_UP) {
9125 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
9127 }
9128 }
9130 if ((ast_channel_state(ast) == AST_STATE_UP) && !p->outgoing) {
9131 /*
9132 * Treat this as a "hangup" instead of a "busy" on the
9133 * assumption that a busy means the incoming call went away.
9134 */
9135 ast_frfree(f);
9136 f = NULL;
9137 }
9138 } else if (p->dialtone_detect && !p->outgoing && f->frametype == AST_FRAME_VOICE) {
9140 /* Dialtone detected on inbound call; hangup the channel */
9141 ast_frfree(f);
9142 f = NULL;
9143 }
9144 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
9145 || f->frametype == AST_FRAME_DTMF_END) {
9146#ifdef HAVE_PRI
9148 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
9149 && p->pri
9150 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
9151 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
9152 /* Don't accept in-band DTMF when in overlap dial mode */
9153 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
9154 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
9155 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
9156
9158 f->subclass.integer = 0;
9159 }
9160#endif
9161 /* DSP clears us of being pulse */
9162 p->pulsedial = 0;
9163 } else if (p->waitingfordt.tv_sec) {
9165 p->waitingfordt.tv_sec = 0;
9166 ast_log(LOG_NOTICE, "Never saw dialtone on channel %d\n", p->channel);
9167 ast_frfree(f);
9168 f = NULL;
9169 } else if (f->frametype == AST_FRAME_VOICE) {
9171 f->subclass.integer = 0;
9173 p->waitingfordt.tv_sec = 0;
9174 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
9176 ast_debug(1, "Got 10 samples of dialtone!\n");
9177 if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
9178 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
9179 if (res) {
9180 p->dop.dialstr[0] = '\0';
9182 ast_frfree(f);
9183 return NULL;
9184 } else {
9185 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
9186 p->dialing = 1;
9187 p->dop.dialstr[0] = '\0';
9188 p->dop.op = DAHDI_DIAL_OP_REPLACE;
9190 }
9191 }
9192 }
9193 }
9194 }
9195 }
9196 } else
9197 f = &p->subs[idx].f;
9198
9199 if (f) {
9200 switch (f->frametype) {
9202 case AST_FRAME_DTMF_END:
9203 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9204 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
9205 } else {
9206 dahdi_handle_dtmf(ast, idx, &f);
9207 }
9209 if (f->frametype == AST_FRAME_DTMF_END) { /* only show this message when the key is let go of */
9210 ast_debug(1, "Dropping DTMF digit '%c' because tone dialing is disabled\n", f->subclass.integer);
9211 }
9213 f->subclass.integer = 0;
9214 }
9215 break;
9216 case AST_FRAME_VOICE:
9217 if (p->cidspill || p->cid_suppress_expire) {
9218 /* We are/were sending a caller id spill. Suppress any echo. */
9219 p->subs[idx].f.frametype = AST_FRAME_NULL;
9220 p->subs[idx].f.subclass.integer = 0;
9221 p->subs[idx].f.samples = 0;
9222 p->subs[idx].f.mallocd = 0;
9223 p->subs[idx].f.offset = 0;
9224 p->subs[idx].f.data.ptr = NULL;
9225 p->subs[idx].f.datalen= 0;
9226 }
9227 break;
9228 default:
9229 break;
9230 }
9231 }
9232
9234 return f;
9235}
static int dahdi_callwait(struct ast_channel *ast)
Definition: chan_dahdi.c:5347
struct ast_format * ast_channel_rawreadformat(struct ast_channel *chan)
#define CHECK_BLOCKING(c)
Set the blocking indication on the channel.
Definition: channel.h:2871
int ast_channel_get_up_time(struct ast_channel *chan)
Obtain how long it has been since the channel was answered.
Definition: channel.c:2845
@ AST_FLAG_BLOCKING
Definition: channel.h:985
int ast_dsp_get_tcount(struct ast_dsp *dsp)
Get tcount (Threshold counter)
Definition: dsp.c:1916
#define DSP_TONE_STATE_DIALTONE
Definition: dsp.h:54
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress,...
Definition: dsp.c:1499
int ast_dsp_get_tstate(struct ast_dsp *dsp)
Get tstate (Tone State)
Definition: dsp.c:1911
int ast_dsp_was_muted(struct ast_dsp *dsp)
Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) hap...
Definition: dsp.c:1906
#define DSP_TONE_STATE_RINGING
Definition: dsp.h:53
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
@ AST_FORMAT_CMP_EQUAL
Definition: format.h:36
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
@ AST_FRAME_VOICE
@ AST_FRAME_TEXT
void analog_handle_dtmf(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub idx, struct ast_frame **dest)
Definition: sig_analog.c:1593
#define DAHDI_OVERLAPDIAL_OUTGOING
Definition: sig_pri.h:252
const ast_string_field name
struct ast_format * format
unsigned int faxdetect_timeout
The number of seconds into call to disable fax detection. (0 = disabled)
Definition: chan_dahdi.h:675
int waitfordialtoneduration
Transient variable. Stored off waitfordialtone duration at runtime.
Definition: chan_dahdi.h:664
unsigned int firstradio
TRUE if over a radio and dahdi_read() has been called.
Definition: chan_dahdi.h:280
short buffer[AST_FRIENDLY_OFFSET/2+READ_SIZE]
Definition: chan_dahdi.h:81
int tdd_feed(struct tdd_state *tdd, unsigned char *ubuf, int samples)
Definition: tdd.c:161

References __dahdi_exception(), ANALOG_DIALMODE_BOTH, ANALOG_DIALMODE_DTMF, analog_exception(), analog_handle_dtmf(), ast_channel_flags(), ast_channel_get_up_time(), ast_channel_name(), ast_channel_rawreadformat(), ast_channel_tech_pvt(), 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_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_slin, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_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, c, 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_analog_lib_handles(), dahdi_callwait(), dahdi_confmute(), dahdi_dial_str(), 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::dialmode, dahdi_pvt::dialtone_detect, dahdi_pvt::dialtone_scanning_time_elapsed, dahdi_pvt::dop, dahdi_pvt::dsp, DSP_FEATURE_FAX_DETECT, 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::faxdetect_timeout, dahdi_pvt::firstradio, ast_frame_subclass::format, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_subchannel::inthreeway, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, dahdi_pvt::muting, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, NULL, ast_frame::offset, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::owner, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::radio, 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(), dahdi_pvt::waitfordialtoneduration, and dahdi_pvt::waitingfordt.

◆ dahdi_request()

static struct ast_channel * dahdi_request ( const char *  type,
struct ast_format_cap cap,
const struct ast_assigned_ids assignedids,
const struct ast_channel requestor,
const char *  data,
int *  cause 
)
static

Definition at line 13891 of file chan_dahdi.c.

13894{
13895 int callwait = 0;
13896 struct dahdi_pvt *p;
13897 struct ast_channel *tmp = NULL;
13898 struct dahdi_pvt *exitpvt;
13899 int channelmatched = 0;
13900 int foundowner = 0;
13901 int groupmatched = 0;
13902#if defined(HAVE_PRI) || defined(HAVE_SS7)
13903 int transcapdigital = 0;
13904#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13905 struct dahdi_starting_point start;
13906 ast_callid callid = 0;
13907 int callid_created = ast_callid_threadstorage_auto(&callid);
13908
13910 p = determine_starting_point(data, &start);
13911 if (!p) {
13912 /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13914 ast_callid_threadstorage_auto_clean(callid, callid_created);
13915 return NULL;
13916 }
13917
13918 /* Search for an unowned channel */
13919 exitpvt = p;
13920 while (p && !tmp) {
13921 if (start.roundrobin)
13922 round_robin[start.rr_starting_point] = p;
13923
13924 if (p->owner) {
13925 foundowner++;
13926 }
13927
13928 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13929 && available(&p, channelmatched)) {
13930 ast_debug(1, "Using channel %d\n", p->channel);
13931
13932 callwait = (p->owner != NULL);
13933#ifdef HAVE_OPENR2
13934 if (p->mfcr2) {
13935 ast_mutex_lock(&p->lock);
13936 if (p->mfcr2call) {
13938 ast_debug(1, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13939 goto next;
13940 }
13941 p->mfcr2call = 1;
13943 }
13944#endif
13945 if (p->channel == CHAN_PSEUDO) {
13946 p = duplicate_pseudo(p);
13947 if (!p) {
13948 break;
13949 }
13950 }
13951
13952 p->distinctivering = 0;
13953 /* Make special notes */
13954 switch (start.opt) {
13955 case '\0':
13956 /* No option present. */
13957 break;
13958 case 'c':
13959 /* Confirm answer */
13960 p->confirmanswer = 1;
13961 break;
13962 case 'r':
13963 /* Distinctive ring */
13964 p->distinctivering = start.cadence;
13965 break;
13966 case 'd':
13967#if defined(HAVE_PRI) || defined(HAVE_SS7)
13968 /* If this is an ISDN call, make it digital */
13969 transcapdigital = AST_TRANS_CAP_DIGITAL;
13970#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13971 break;
13972 default:
13973 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, data);
13974 break;
13975 }
13976
13977 p->outgoing = 1;
13978 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13979 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13980#ifdef HAVE_PRI
13981 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13982 /*
13983 * We already have the B channel reserved for this call. We
13984 * just need to make sure that dahdi_hangup() has completed
13985 * cleaning up before continuing.
13986 */
13987 ast_mutex_lock(&p->lock);
13989
13991 sizeof(p->dnid));
13992 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, assignedids, requestor, transcapdigital);
13993#endif
13994#if defined(HAVE_SS7)
13995 } else if (p->sig == SIG_SS7) {
13996 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, assignedids, requestor, transcapdigital);
13997#endif /* defined(HAVE_SS7) */
13998 } else {
13999 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, assignedids, requestor, callid);
14000 }
14001 if (!tmp) {
14002 p->outgoing = 0;
14003#if defined(HAVE_PRI)
14004 switch (p->sig) {
14006#if defined(HAVE_PRI_CALL_WAITING)
14007 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
14008 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
14009 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
14010 }
14011#endif /* defined(HAVE_PRI_CALL_WAITING) */
14012 /*
14013 * This should be the last thing to clear when we are done with
14014 * the channel.
14015 */
14016 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
14017 break;
14018 default:
14019 break;
14020 }
14021#endif /* defined(HAVE_PRI) */
14022 } else {
14023 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", data);
14024 }
14025 break;
14026 }
14027#ifdef HAVE_OPENR2
14028next:
14029#endif
14030 if (start.backwards) {
14031 p = p->prev;
14032 if (!p)
14033 p = ifend;
14034 } else {
14035 p = p->next;
14036 if (!p)
14037 p = iflist;
14038 }
14039 /* stop when you roll to the one that we started from */
14040 if (p == exitpvt)
14041 break;
14042 }
14045 if (cause && !tmp) {
14046 if (callwait || (channelmatched && foundowner)) {
14047 *cause = AST_CAUSE_BUSY;
14048 } else if (groupmatched) {
14049 *cause = AST_CAUSE_CONGESTION;
14050 } else {
14051 /*
14052 * We did not match any channel requested.
14053 * Dialplan error requesting non-existant channel?
14054 */
14055 }
14056 }
14057
14058 ast_callid_threadstorage_auto_clean(callid, callid_created);
14059 return tmp;
14060}
#define AST_CAUSE_BUSY
Definition: causes.h:149
static struct dahdi_pvt * round_robin[64]
Definition: chan_dahdi.c:3678
static int available(struct dahdi_pvt **pvt, int is_specific_channel)
Definition: chan_dahdi.c:13460
static struct dahdi_pvt * duplicate_pseudo(struct dahdi_pvt *src)
Definition: chan_dahdi.c:13666
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
struct ast_channel * analog_request(struct analog_pvt *p, int *callwait, const struct ast_channel *requestor)
Definition: sig_analog.c:770
@ SIG_PRI_DEFLAW
Definition: sig_pri.h:68
struct ast_channel * sig_pri_request(struct sig_pri_chan *p, enum sig_pri_law law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int transfercapability)
struct ast_channel * sig_ss7_request(struct sig_ss7_chan *p, enum sig_ss7_law law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int transfercapability)
@ SIG_SS7_DEFLAW
Definition: sig_ss7.h:89
char dialstring[AST_CHANNEL_NAME]
Definition: chan_dahdi.h:772
#define AST_TRANS_CAP_DIGITAL
Definition: transcap.h:36

References analog_request(), ast_atomic_fetchadd_int(), ast_callid_threadstorage_auto(), ast_callid_threadstorage_auto_clean(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, AST_STATE_RESERVED, AST_TRANS_CAP_DIGITAL, available(), dahdi_starting_point::backwards, dahdi_starting_point::cadence, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_starting_point::channelmatch, dahdi_pvt::confirmanswer, dahdi_analog_lib_handles(), 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, ifend, iflist, iflock, is_group_or_channel_match(), dahdi_pvt::lock, LOG_WARNING, dahdi_pvt::next, NULL, dahdi_pvt::oprmode, dahdi_starting_point::opt, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::radio, restart_monitor(), round_robin, 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, SUB_REAL, and tmp().

◆ dahdi_restart()

static int dahdi_restart ( void  )
static

Definition at line 15829 of file chan_dahdi.c.

15830{
15831#if defined(HAVE_PRI) || defined(HAVE_SS7)
15832 int i, j;
15833#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15834 int cancel_code;
15835 struct dahdi_pvt *p;
15836
15838 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15840 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15841#ifdef HAVE_OPENR2
15842 dahdi_r2_destroy_links();
15843#endif
15844
15845#if defined(HAVE_PRI)
15846 for (i = 0; i < NUM_SPANS; i++) {
15847 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15848 cancel_code = pthread_cancel(pris[i].pri.master);
15849 pthread_kill(pris[i].pri.master, SIGURG);
15850 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);
15851 pthread_join(pris[i].pri.master, NULL);
15852 ast_debug(4, "Joined thread of span %d\n", i);
15853 }
15854 }
15855#endif
15856
15857#if defined(HAVE_SS7)
15858 for (i = 0; i < NUM_SPANS; i++) {
15859 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15860 cancel_code = pthread_cancel(linksets[i].ss7.master);
15861 pthread_kill(linksets[i].ss7.master, SIGURG);
15862 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);
15863 pthread_join(linksets[i].ss7.master, NULL);
15864 ast_debug(4, "Joined thread of span %d\n", i);
15865 }
15866 }
15867#endif /* defined(HAVE_SS7) */
15868
15871 cancel_code = pthread_cancel(monitor_thread);
15872 pthread_kill(monitor_thread, SIGURG);
15873 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15874 pthread_join(monitor_thread, NULL);
15875 ast_debug(4, "Joined monitor thread\n");
15876 }
15877 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15878
15880 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15881 int x = DAHDI_FLASH;
15882 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15883
15885 for (p = iflist; p; p = p->next) {
15886 if (p->owner) {
15887 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15888 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15889 }
15890 }
15893 }
15894
15895 /* ensure any created channels before monitor threads were stopped are hungup */
15897 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15899 memset(round_robin, 0, sizeof(round_robin));
15900 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15901
15903
15904#ifdef HAVE_PRI
15905 for (i = 0; i < NUM_SPANS; i++) {
15906 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15907 dahdi_close_pri_fd(&(pris[i]), j);
15908 }
15909
15910 memset(pris, 0, sizeof(pris));
15911 for (i = 0; i < NUM_SPANS; i++) {
15912 sig_pri_init_pri(&pris[i].pri);
15913 }
15914 pri_set_error(dahdi_pri_error);
15915 pri_set_message(dahdi_pri_message);
15916#endif
15917#if defined(HAVE_SS7)
15918 for (i = 0; i < NUM_SPANS; i++) {
15919 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15920 dahdi_close_ss7_fd(&(linksets[i]), j);
15921 }
15922
15923 memset(linksets, 0, sizeof(linksets));
15924 for (i = 0; i < NUM_SPANS; i++) {
15925 sig_ss7_init_linkset(&linksets[i].ss7);
15926 }
15927 ss7_set_error(dahdi_ss7_error);
15928 ss7_set_message(dahdi_ss7_message);
15929 ss7_set_hangup(sig_ss7_cb_hangup);
15930 ss7_set_notinservice(sig_ss7_cb_notinservice);
15931 ss7_set_call_null(sig_ss7_cb_call_null);
15932#endif /* defined(HAVE_SS7) */
15933
15934 if (setup_dahdi(2) != 0) {
15935 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15937 return 1;
15938 }
15941 return 0;
15942}
static void dahdi_softhangup_all(void)
Definition: chan_dahdi.c:15801
static int setup_dahdi(int reload)
Definition: chan_dahdi.c:20238
static ast_mutex_t restart_lock
Definition: chan_dahdi.c:764
int ast_active_channels(void)
returns number of active/allocated channels
Definition: channel.c:499
#define ast_cond_wait(cond, mutex)
Definition: lock.h:205
void sig_pri_init_pri(struct sig_pri_span *pri)
void sig_ss7_cb_call_null(struct ss7 *ss7, struct isup_call *c, int lock)
void sig_ss7_init_linkset(struct sig_ss7_linkset *ss7)
void sig_ss7_cb_notinservice(struct ss7 *ss7, int cic, unsigned int dpc)
int sig_ss7_cb_hangup(struct ss7 *ss7, int cic, unsigned int dpc, int cause, int do_hangup)

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, iflist, iflock, LOG_WARNING, sig_pri_span::master, monitor_thread, monlock, dahdi_pvt::next, NULL, NUM_SPANS, dahdi_pvt::owner, restart_lock, round_robin, setup_dahdi(), sig_pri_init_pri(), SIG_PRI_NUM_DCHANS, sig_ss7_cb_call_null(), sig_ss7_cb_hangup(), sig_ss7_cb_notinservice(), sig_ss7_init_linkset(), SIG_SS7_NUM_DCHANS, ss_thread_complete, ss_thread_count, ss_thread_lock, SUB_REAL, and dahdi_pvt::subs.

Referenced by action_dahdirestart(), and dahdi_restart_cmd().

◆ dahdi_restart_cmd()

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

Definition at line 15944 of file chan_dahdi.c.

15945{
15946 switch (cmd) {
15947 case CLI_INIT:
15948 e->command = "dahdi restart";
15949 e->usage =
15950 "Usage: dahdi restart\n"
15951 " Restarts the DAHDI channels: destroys them all and then\n"
15952 " re-reads them from chan_dahdi.conf.\n"
15953 " Note that this will STOP any running CALL on DAHDI channels.\n"
15954 "";
15955 return NULL;
15956 case CLI_GENERATE:
15957 return NULL;
15958 }
15959 if (a->argc != 2)
15960 return CLI_SHOWUSAGE;
15961
15962 if (dahdi_restart() != 0)
15963 return CLI_FAILURE;
15964 return CLI_SUCCESS;
15965}

References a, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_restart(), NULL, and ast_cli_entry::usage.

◆ dahdi_ring_phone()

static int dahdi_ring_phone ( struct dahdi_pvt p)
static

Definition at line 7452 of file chan_dahdi.c.

7453{
7454 int x;
7455 int res;
7456 /* Make sure our transmit state is on hook */
7457 x = 0;
7458 x = DAHDI_ONHOOK;
7459 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7460 do {
7461 x = DAHDI_RING;
7462 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7463 if (res) {
7464 switch (errno) {
7465 case EBUSY:
7466 case EINTR:
7467 /* Wait just in case */
7468 usleep(10000);
7469 continue;
7470 case EINPROGRESS:
7471 res = 0;
7472 break;
7473 default:
7474 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
7475 res = 0;
7476 }
7477 }
7478 } while (res);
7479 return res;
7480}

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

◆ dahdi_sendtext()

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

Definition at line 20376 of file chan_dahdi.c.

20377{
20378#define END_SILENCE_LEN 400
20379#define HEADER_MS 50
20380#define TRAILER_MS 5
20381#define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
20382#define ASCII_BYTES_PER_CHAR 80
20383
20384 unsigned char *buf,*mybuf;
20385 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
20386 struct pollfd fds[1];
20387 int size,res,fd,len,x;
20388 int bytes=0;
20389 int idx;
20390
20391 /*
20392 * Initial carrier (imaginary)
20393 *
20394 * Note: The following float variables are used by the
20395 * PUT_CLID_MARKMS and PUT_CLID() macros.
20396 */
20397 float cr = 1.0;
20398 float ci = 0.0;
20399 float scont = 0.0;
20400
20401 if (!text[0]) {
20402 return(0); /* if nothing to send, don't */
20403 }
20404 idx = dahdi_get_index(c, p, 0);
20405 if (idx < 0) {
20406 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
20407 return -1;
20408 }
20409 if ((!p->tdd) && (!p->mate)) {
20410#if defined(HAVE_PRI)
20411#if defined(HAVE_PRI_DISPLAY_TEXT)
20412 ast_mutex_lock(&p->lock);
20414 sig_pri_sendtext(p->sig_pvt, text);
20415 }
20417#endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
20418#endif /* defined(HAVE_PRI) */
20419 return(0); /* if not in TDD mode, just return */
20420 }
20421 if (p->mate)
20423 else
20424 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
20425 if (!buf)
20426 return -1;
20427 mybuf = buf;
20428 if (p->mate) {
20429 /* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
20430 struct ast_format *codec = AST_LAW(p);
20431
20432 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
20434 }
20435 /* Put actual message */
20436 for (x = 0; text[x]; x++) {
20437 PUT_CLID(text[x]);
20438 }
20439 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
20441 }
20442 len = bytes;
20443 buf = mybuf;
20444 } else {
20445 len = tdd_generate(p->tdd, buf, text);
20446 if (len < 1) {
20447 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
20448 ast_free(mybuf);
20449 return -1;
20450 }
20451 }
20452 memset(buf + len, 0x7f, END_SILENCE_LEN);
20454 fd = p->subs[idx].dfd;
20455 while (len) {
20456 if (ast_check_hangup(c)) {
20457 ast_free(mybuf);
20458 return -1;
20459 }
20460 size = len;
20461 if (size > READ_SIZE)
20462 size = READ_SIZE;
20463 fds[0].fd = fd;
20464 fds[0].events = POLLOUT | POLLPRI;
20465 fds[0].revents = 0;
20466 res = poll(fds, 1, -1);
20467 if (!res) {
20468 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
20469 continue;
20470 }
20471 /* if got exception */
20472 if (fds[0].revents & POLLPRI) {
20473 ast_free(mybuf);
20474 return -1;
20475 }
20476 if (!(fds[0].revents & POLLOUT)) {
20477 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
20478 continue;
20479 }
20480 res = write(fd, buf, size);
20481 if (res != size) {
20482 if (res == -1) {
20483 ast_free(mybuf);
20484 return -1;
20485 }
20486 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
20487 break;
20488 }
20489 len -= size;
20490 buf += size;
20491 }
20492 ast_free(mybuf);
20493 return(0);
20494}
char * text
Definition: app_queue.c:1639
#define PUT_CLID(byte)
Definition: callerid.h:398
#define PUT_CLID_MARKMS
Definition: callerid.h:383
#define HEADER_MS
#define END_SILENCE_LEN
#define TRAILER_MS
#define ASCII_BYTES_PER_CHAR
#define HEADER_LEN
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
struct ast_codec * codec
Pointer to the codec in use for this format.
Definition: format.c:47
#define TDD_BYTES_PER_CHAR
Definition: tdd.h:27
int tdd_generate(struct tdd_state *tdd, unsigned char *buf, const char *string)
Definition: tdd.c:296

References ASCII_BYTES_PER_CHAR, ast_channel_tech_pvt(), ast_check_hangup(), ast_debug, ast_free, AST_LAW, ast_log, ast_malloc, ast_mutex_lock, ast_mutex_unlock, buf, c, dahdi_pvt::channel, ast_format::codec, 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(), text, and TRAILER_MS.

◆ dahdi_set_dnd()

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

Definition at line 16583 of file chan_dahdi.c.

16584{
16585 int channel;
16586 int on;
16587 struct dahdi_pvt *dahdi_chan = NULL;
16588
16589 switch (cmd) {
16590 case CLI_INIT:
16591 e->command = "dahdi set dnd";
16592 e->usage =
16593 "Usage: dahdi set dnd <chan#> <on|off>\n"
16594 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16595 " Changes take effect immediately.\n"
16596 " <chan num> is the channel number\n"
16597 " <on|off> Enable or disable DND mode?\n"
16598 ;
16599 return NULL;
16600 case CLI_GENERATE:
16601 return NULL;
16602 }
16603
16604 if (a->argc != 5)
16605 return CLI_SHOWUSAGE;
16606
16607 if ((channel = atoi(a->argv[3])) <= 0) {
16608 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16609 return CLI_SHOWUSAGE;
16610 }
16611
16612 if (ast_true(a->argv[4]))
16613 on = 1;
16614 else if (ast_false(a->argv[4]))
16615 on = 0;
16616 else {
16617 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16618 return CLI_SHOWUSAGE;
16619 }
16620
16622 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16623 if (dahdi_chan->channel != channel)
16624 continue;
16625
16626 /* Found the channel. Actually set it */
16627 dahdi_dnd(dahdi_chan, on);
16628 break;
16629 }
16631
16632 if (!dahdi_chan) {
16633 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16634 return CLI_FAILURE;
16635 }
16636
16637 return CLI_SUCCESS;
16638}
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition: utils.c:2216

References a, 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(), iflist, iflock, dahdi_pvt::next, NULL, and ast_cli_entry::usage.

◆ dahdi_set_hook()

static int dahdi_set_hook ( int  fd,
int  hs 
)
inlinestatic

Definition at line 5170 of file chan_dahdi.c.

5171{
5172 int x, res;
5173
5174 x = hs;
5175 res = ioctl(fd, DAHDI_HOOK, &x);
5176
5177 if (res < 0) {
5178 if (errno == EINPROGRESS)
5179 return 0;
5180 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
5181 /* will expectedly fail if phone is off hook during operation, such as during a restart */
5182 }
5183
5184 return res;
5185}

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

◆ dahdi_set_hwgain()

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

Definition at line 16426 of file chan_dahdi.c.

16427{
16428 int channel;
16429 float gain;
16430 int tx;
16431 struct dahdi_pvt *tmp = NULL;
16432
16433 switch (cmd) {
16434 case CLI_INIT:
16435 e->command = "dahdi set hwgain {rx|tx}";
16436 e->usage =
16437 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
16438 " Sets the hardware gain on a given channel and overrides the\n"
16439 " value provided at module loadtime. Changes take effect\n"
16440 " immediately whether the channel is in use or not.\n"
16441 "\n"
16442 " <rx|tx> which direction do you want to change (relative to our module)\n"
16443 " <chan num> is the channel number relative to the device\n"
16444 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
16445 "\n"
16446 " Please note:\n"
16447 " * hwgain is only supportable by hardware with analog ports because\n"
16448 " hwgain works on the analog side of an analog-digital conversion.\n";
16449 return NULL;
16450 case CLI_GENERATE:
16451 return NULL;
16452 }
16453
16454 if (a->argc != 6)
16455 return CLI_SHOWUSAGE;
16456
16457 if (!strcasecmp("rx", a->argv[3]))
16458 tx = 0; /* rx */
16459 else if (!strcasecmp("tx", a->argv[3]))
16460 tx = 1; /* tx */
16461 else
16462 return CLI_SHOWUSAGE;
16463
16464 channel = atoi(a->argv[4]);
16465 gain = atof(a->argv[5]);
16466
16468
16469 for (tmp = iflist; tmp; tmp = tmp->next) {
16470
16471 if (tmp->channel != channel)
16472 continue;
16473
16474 if (tmp->subs[SUB_REAL].dfd == -1)
16475 break;
16476
16477 if (set_hwgain(tmp->subs[SUB_REAL].dfd, gain, tx)) {
16478 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
16480 return CLI_FAILURE;
16481 }
16482 ast_cli(a->fd, "Hardware %s gain set to %.1f dB on channel %d.\n",
16483 tx ? "tx" : "rx", gain, channel);
16484
16485 if (tx) {
16486 tmp->hwtxgain_enabled = 1;
16487 tmp->hwtxgain = gain;
16488 } else {
16489 tmp->hwrxgain_enabled = 1;
16490 tmp->hwrxgain = gain;
16491 }
16492 break;
16493 }
16494
16496
16497 if (tmp)
16498 return CLI_SUCCESS;
16499
16500 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16501 return CLI_FAILURE;
16502
16503}
static int set_hwgain(int fd, float gain, int tx_direction)
Definition: chan_dahdi.c:4976

References a, 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, errno, iflist, iflock, NULL, set_hwgain(), SUB_REAL, tmp(), and ast_cli_entry::usage.

◆ dahdi_set_mwi()

static char * dahdi_set_mwi ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 16640 of file chan_dahdi.c.

16641{
16642 int channel;
16643 int on;
16644 int override = 1;
16645 struct dahdi_pvt *dahdi_chan = NULL;
16646
16647 switch (cmd) {
16648 case CLI_INIT:
16649 e->command = "dahdi set mwi";
16650 e->usage =
16651 "Usage: dahdi set mwi <chan#> <on|off|reset>\n"
16652 " Sets/unsets MWI (Message Waiting Indicator) manually on a channel.\n"
16653 " This may be used regardless of whether the channel is assigned any mailboxes.\n"
16654 " When active, this setting will override the voicemail status to set MWI.\n"
16655 " Once cleared, the voicemail status will resume control of MWI.\n"
16656 " Changes are queued for when the channel is idle and persist until cleared.\n"
16657 " <chan num> is the channel number\n"
16658 " <on|off|reset> Enable, disable, or reset Message Waiting Indicator override?\n"
16659 ;
16660 return NULL;
16661 case CLI_GENERATE:
16662 return NULL;
16663 }
16664
16665 if (a->argc != 5)
16666 return CLI_SHOWUSAGE;
16667
16668 if ((channel = atoi(a->argv[3])) <= 0) {
16669 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16670 return CLI_SHOWUSAGE;
16671 }
16672
16673 if (ast_true(a->argv[4])) {
16674 on = 1;
16675 } else if (ast_false(a->argv[4])) {
16676 on = 0;
16677 } else if (!strcmp(a->argv[4], "reset")) {
16678 override = 0;
16679 } else {
16680 ast_cli(a->fd, "Expected 'on' or 'off' or 'reset', got '%s'\n", a->argv[4]);
16681 return CLI_SHOWUSAGE;
16682 }
16683
16685 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16686 if (dahdi_chan->channel != channel)
16687 continue;
16688
16689 /* Found the channel. Actually set it */
16690 if (override) {
16691 dahdi_chan->mwioverride_disposition = on;
16692 ast_cli(a->fd, "MWI '%s' queued for channel %d\n", on ? "enable" : "disable", channel);
16693 }
16694 dahdi_chan->mwioverride_active = override;
16695 /* The do_monitor thread will take care of actually sending the MWI
16696 * at an appropriate time for the channel. */
16697 break;
16698 }
16700
16701 if (!dahdi_chan) {
16702 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16703 return CLI_FAILURE;
16704 }
16705
16706 return CLI_SUCCESS;
16707}
unsigned int mwioverride_active
TRUE if a manual MWI override is active for a channel.
Definition: chan_dahdi.h:435
unsigned int mwioverride_disposition
Manual MWI disposition (on/off)
Definition: chan_dahdi.h:437

References a, 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, iflist, iflock, dahdi_pvt::mwioverride_active, dahdi_pvt::mwioverride_disposition, dahdi_pvt::next, NULL, and ast_cli_entry::usage.

◆ dahdi_set_swgain()

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

Definition at line 16505 of file chan_dahdi.c.

16506{
16507 int channel;
16508 float gain;
16509 int tx;
16510 int res;
16511 struct dahdi_pvt *tmp = NULL;
16512
16513 switch (cmd) {
16514 case CLI_INIT:
16515 e->command = "dahdi set swgain {rx|tx}";
16516 e->usage =
16517 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
16518 " Sets the software gain on a given channel and overrides the\n"
16519 " value provided at module loadtime. Changes take effect\n"
16520 " immediately whether the channel is in use or not.\n"
16521 "\n"
16522 " <rx|tx> which direction do you want to change (relative to our module)\n"
16523 " <chan num> is the channel number relative to the device\n"
16524 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16525 return NULL;
16526 case CLI_GENERATE:
16527 return NULL;
16528 }
16529
16530 if (a->argc != 6)
16531 return CLI_SHOWUSAGE;
16532
16533 if (!strcasecmp("rx", a->argv[3]))
16534 tx = 0; /* rx */
16535 else if (!strcasecmp("tx", a->argv[3]))
16536 tx = 1; /* tx */
16537 else
16538 return CLI_SHOWUSAGE;
16539
16540 channel = atoi(a->argv[4]);
16541 gain = atof(a->argv[5]);
16542
16544 for (tmp = iflist; tmp; tmp = tmp->next) {
16545
16546 if (tmp->channel != channel)
16547 continue;
16548
16549 if (tmp->subs[SUB_REAL].dfd == -1)
16550 break;
16551
16552 if (tx)
16553 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
16554 else
16555 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
16556
16557 if (res) {
16558 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
16560 return CLI_FAILURE;
16561 }
16562
16563 ast_cli(a->fd, "Software %s gain set to %.2f dB on channel %d.\n",
16564 tx ? "tx" : "rx", gain, channel);
16565
16566 if (tx) {
16567 tmp->txgain = gain;
16568 } else {
16569 tmp->rxgain = gain;
16570 }
16571 break;
16572 }
16574
16575 if (tmp)
16576 return CLI_SUCCESS;
16577
16578 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16579 return CLI_FAILURE;
16580
16581}
static int set_actual_txgain(int fd, float gain, float drc, int law)
Definition: chan_dahdi.c:5104
static int set_actual_rxgain(int fd, float gain, float drc, int law)
Definition: chan_dahdi.c:5121

References a, 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, iflist, iflock, NULL, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, tmp(), and ast_cli_entry::usage.

◆ dahdi_setlinear()

static int dahdi_setlinear ( int  dfd,
int  linear 
)
static

Definition at line 4409 of file chan_dahdi.c.

4410{
4411 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
4412}

Referenced by analog_ss_thread(), dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), my_all_subchannels_hungup(), my_set_linear_mode(), my_start_cid_detect(), my_stop_cid_detect(), and send_callerid().

◆ dahdi_setoption()

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

6832{
6833 char *cp;
6834 signed char *scp;
6835 int x;
6836 int idx;
6837 struct dahdi_pvt *p = ast_channel_tech_pvt(chan), *pp;
6838 struct oprmode *oprmode;
6839
6840
6841 /* all supported options require data */
6842 if (!p || !data || (datalen < 1)) {
6843 errno = EINVAL;
6844 return -1;
6845 }
6846
6847 switch (option) {
6848 case AST_OPTION_TXGAIN:
6849 scp = (signed char *) data;
6850 idx = dahdi_get_index(chan, p, 0);
6851 if (idx < 0) {
6852 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
6853 return -1;
6854 }
6855 ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
6856 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
6857 case AST_OPTION_RXGAIN:
6858 scp = (signed char *) data;
6859 idx = dahdi_get_index(chan, p, 0);
6860 if (idx < 0) {
6861 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
6862 return -1;
6863 }
6864 ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
6865 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
6867 if (!p->dsp)
6868 break;
6869 cp = (char *) data;
6870 switch (*cp) {
6871 case 1:
6872 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
6873 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
6874 break;
6875 case 2:
6876 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
6877 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
6878 break;
6879 default:
6880 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
6881 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
6882 break;
6883 }
6884 break;
6885 case AST_OPTION_TDD:
6886 /* turn on or off TDD */
6887 cp = (char *) data;
6888 p->mate = 0;
6889 if (!*cp) { /* turn it off */
6890 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
6891 if (p->tdd)
6892 tdd_free(p->tdd);
6893 p->tdd = 0;
6894 break;
6895 }
6896 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
6897 (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
6899 /* otherwise, turn it on */
6900 if (!p->didtdd) { /* if havent done it yet */
6901 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
6902 unsigned char *buf;
6903 int size, res, fd, len;
6904 struct pollfd fds[1];
6905
6906 buf = mybuf;
6907 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
6908 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
6909 len = 40000;
6910 idx = dahdi_get_index(chan, p, 0);
6911 if (idx < 0) {
6912 ast_log(LOG_WARNING, "No index in TDD?\n");
6913 return -1;
6914 }
6915 fd = p->subs[idx].dfd;
6916 while (len) {
6917 if (ast_check_hangup(chan))
6918 return -1;
6919 size = len;
6920 if (size > READ_SIZE)
6921 size = READ_SIZE;
6922 fds[0].fd = fd;
6923 fds[0].events = POLLPRI | POLLOUT;
6924 fds[0].revents = 0;
6925 res = poll(fds, 1, -1);
6926 if (!res) {
6927 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
6928 continue;
6929 }
6930 /* if got exception */
6931 if (fds[0].revents & POLLPRI)
6932 return -1;
6933 if (!(fds[0].revents & POLLOUT)) {
6934 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
6935 continue;
6936 }
6937 res = write(fd, buf, size);
6938 if (res != size) {
6939 if (res == -1) return -1;
6940 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
6941 break;
6942 }
6943 len -= size;
6944 buf += size;
6945 }
6946 p->didtdd = 1; /* set to have done it now */
6947 }
6948 if (*cp == 2) { /* Mate mode */
6949 if (p->tdd)
6950 tdd_free(p->tdd);
6951 p->tdd = 0;
6952 p->mate = 1;
6953 break;
6954 }
6955 if (!p->tdd) { /* if we don't have one yet */
6956 p->tdd = tdd_new(); /* allocate one */
6957 }
6958 break;
6959 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
6960 if (!p->dsp)
6961 break;
6962 cp = (char *) data;
6963 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
6964 *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
6966 break;
6967 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
6968#if defined(HAVE_PRI)
6970 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
6971 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
6972 break;
6973 }
6974#endif /* defined(HAVE_PRI) */
6975
6976 cp = (char *) data;
6977 if (!*cp) {
6978 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
6979 x = 0;
6981 } else {
6982 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
6983 x = 1;
6984 }
6985 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
6986 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
6987 break;
6988 case AST_OPTION_OPRMODE: /* Operator services mode */
6989 oprmode = (struct oprmode *) data;
6990 /* We don't support operator mode across technologies */
6991 if (strcasecmp(ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type)) {
6992 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
6994 errno = EINVAL;
6995 return -1;
6996 }
6998 p->oprmode = pp->oprmode = 0;
6999 /* setup peers */
7000 p->oprpeer = pp;
7001 pp->oprpeer = p;
7002 /* setup modes, if any */
7003 if (oprmode->mode)
7004 {
7005 pp->oprmode = oprmode->mode;
7006 p->oprmode = -oprmode->mode;
7007 }
7008 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
7010 break;
7011 case AST_OPTION_ECHOCAN:
7012 cp = (char *) data;
7013 if (*cp) {
7014 ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
7015 dahdi_ec_enable(p);
7016 } else {
7017 ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
7019 }
7020 break;
7022 cp = (char *) data;
7023 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
7024 if (*cp) {
7026 } else {
7028 }
7029 break;
7031 cp = (char *) data;
7032 if (p->dsp) {
7033 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
7034 if (*cp) {
7036 } else {
7037 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
7038 }
7040 }
7041 break;
7042 default:
7043 return -1;
7044 }
7045 errno = 0;
7046
7047 return 0;
7048}
void dahdi_dtmf_detect_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:6765
void dahdi_dtmf_detect_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:6751
#define DSP_DIGITMODE_MUTEMAX
Definition: dsp.h:36
#define DSP_DIGITMODE_MUTECONF
Definition: dsp.h:35
#define DSP_DIGITMODE_RELAXDTMF
Definition: dsp.h:37
#define AST_OPTION_RELAXDTMF
#define AST_OPTION_RXGAIN
#define AST_OPTION_OPRMODE
#define AST_OPTION_TXGAIN
#define AST_OPTION_ECHOCAN
const char *const type
Definition: channel.h:629
struct ast_channel * peer
struct tdd_state * tdd_new(void)
Definition: tdd.c:103
void tdd_free(struct tdd_state *tdd)
Definition: tdd.c:218
int ast_tdd_gen_ecdisa(unsigned char *outbuf, int len)
Definition: tdd.c:148

References ast_channel_name(), ast_channel_tech(), ast_channel_tech_pvt(), 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(), buf, dahdi_pvt::channel, dahdi_dtmf_detect_disable(), dahdi_dtmf_detect_enable(), dahdi_ec_disable(), dahdi_ec_enable(), dahdi_get_index, dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, 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, errno, dahdi_pvt::law, len(), LOG_NOTICE, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, oprmode::peer, READ_SIZE, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), dahdi_pvt::sig, dahdi_pvt::sig_pvt, SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), dahdi_pvt::txdrc, dahdi_pvt::txgain, type, and ast_channel_tech::type.

◆ dahdi_show_channel()

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

Definition at line 16058 of file chan_dahdi.c.

16059{
16060 int channel;
16061 struct dahdi_pvt *tmp = NULL;
16062 struct dahdi_confinfo ci;
16063 struct dahdi_params ps;
16064 int x;
16065 char hwrxgain[15];
16066 char hwtxgain[15];
16067
16068 switch (cmd) {
16069 case CLI_INIT:
16070 e->command = "dahdi show channel";
16071 e->usage =
16072 "Usage: dahdi show channel <chan num>\n"
16073 " Detailed information about a given channel\n";
16074 return NULL;
16075 case CLI_GENERATE:
16076 return NULL;
16077 }
16078
16079 if (a->argc != 4)
16080 return CLI_SHOWUSAGE;
16081
16082 channel = atoi(a->argv[3]);
16083
16085 for (tmp = iflist; tmp; tmp = tmp->next) {
16086 if (tmp->channel == channel) {
16087 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
16088 ast_cli(a->fd, "Description: %s\n", tmp->description);
16089 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
16090 ast_cli(a->fd, "Span: %d\n", tmp->span);
16091 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
16092 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
16093 ast_cli(a->fd, "Context: %s\n", tmp->context);
16094 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
16095 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
16096#if defined(HAVE_PRI)
16097#if defined(HAVE_PRI_SUBADDR)
16098 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
16099#endif /* defined(HAVE_PRI_SUBADDR) */
16100#endif /* defined(HAVE_PRI) */
16101 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
16102 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
16103 if (tmp->vars) {
16104 struct ast_variable *v;
16105 ast_cli(a->fd, "Variables:\n");
16106 for (v = tmp->vars ; v ; v = v->next)
16107 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
16108 }
16109 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
16110 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
16111 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
16112 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
16113 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? ast_channel_name(tmp->owner) : "<None>");
16114 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)" : "");
16115 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)" : "");
16116 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)" : "");
16117 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
16118 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
16119 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
16120 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
16121 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
16122 if (tmp->busydetect) {
16123#if defined(BUSYDETECT_TONEONLY)
16124 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
16125#elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
16126 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
16127#endif
16128#ifdef BUSYDETECT_DEBUG
16129 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
16130#endif
16131 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
16132 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);
16133 }
16134 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
16135 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
16136 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
16137 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
16138 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
16139 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
16140 if (tmp->hwrxgain_enabled) {
16141 snprintf(hwrxgain, sizeof(hwrxgain), "%.1f", tmp->hwrxgain);
16142 } else {
16143 ast_copy_string(hwrxgain, "Disabled", sizeof(hwrxgain));
16144 }
16145 if (tmp->hwtxgain_enabled) {
16146 snprintf(hwtxgain, sizeof(hwtxgain), "%.1f", tmp->hwtxgain);
16147 } else {
16148 ast_copy_string(hwtxgain, "Disabled", sizeof(hwtxgain));
16149 }
16150 ast_cli(a->fd, "HW Gains (RX/TX): %s/%s\n", hwrxgain, hwtxgain);
16151 ast_cli(a->fd, "SW Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
16152 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
16153 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
16154 ast_cli(a->fd, "Echo Cancellation:\n");
16155
16156 if (tmp->echocancel.head.tap_length) {
16157 ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length);
16158 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
16159 ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
16160 }
16161 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
16162 } else {
16163 ast_cli(a->fd, "\tnone\n");
16164 }
16165 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
16166 if (tmp->master)
16167 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
16168 for (x = 0; x < MAX_SLAVES; x++) {
16169 if (tmp->slaves[x])
16170 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
16171 }
16172#ifdef HAVE_OPENR2
16173 if (tmp->mfcr2) {
16174 char calldir[OR2_MAX_PATH];
16175 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
16176 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
16177 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
16178 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
16179 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
16180 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
16181 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
16182 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
16183 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
16184 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
16185#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
16186 ast_cli(a->fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
16187 ast_cli(a->fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
16188#endif
16189 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
16190#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
16191 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
16192#endif
16193 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
16194 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
16195 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
16196 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
16197 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
16198 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
16199 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
16200 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
16201 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
16202 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
16203 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
16204 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
16205 }
16206#endif
16207#if defined(HAVE_SS7)
16208 if (tmp->ss7) {
16209 struct sig_ss7_chan *chan = tmp->sig_pvt;
16210
16211 ast_cli(a->fd, "CIC: %d\n", chan->cic);
16212 }
16213#endif /* defined(HAVE_SS7) */
16214#ifdef HAVE_PRI
16215 if (tmp->pri) {
16216 struct sig_pri_chan *chan = tmp->sig_pvt;
16217
16218 ast_cli(a->fd, "PRI Flags: ");
16219 if (chan->resetting != SIG_PRI_RESET_IDLE) {
16220 ast_cli(a->fd, "Resetting=%u ", chan->resetting);
16221 }
16222 if (chan->call)
16223 ast_cli(a->fd, "Call ");
16224 if (chan->allocated) {
16225 ast_cli(a->fd, "Allocated ");
16226 }
16227 ast_cli(a->fd, "\n");
16228 if (tmp->logicalspan)
16229 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
16230 else
16231 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
16232 }
16233#endif
16234 memset(&ci, 0, sizeof(ci));
16235 ps.channo = tmp->channel;
16236 if (tmp->subs[SUB_REAL].dfd > -1) {
16237 memset(&ci, 0, sizeof(ci));
16238 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
16239 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode);
16240 }
16241 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
16242 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
16243 }
16244 memset(&ps, 0, sizeof(ps));
16245 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
16246 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
16247 } else {
16248 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
16249 }
16250 }
16252 return CLI_SUCCESS;
16253 }
16254 }
16256
16257 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16258 return CLI_FAILURE;
16259}
@ SIG_PRI_RESET_IDLE
The channel is not being RESTARTed.
Definition: sig_pri.h:154
enum sig_pri_reset_state resetting
Channel reset/restart state.
Definition: sig_pri.h:361
unsigned int allocated
TRUE when this channel is allocated.
Definition: sig_pri.h:339
int channel
Definition: sig_pri.h:290
q931_call * call
Definition: sig_pri.h:356

References a, sig_pri_chan::allocated, ast_channel_name(), ast_cli(), ast_copy_string(), ast_log, ast_mutex_lock, ast_mutex_unlock, sig_pri_chan::call, dahdi_pvt::channel, sig_pri_chan::channel, sig_ss7_chan::cic, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_dnd(), errno, iflist, iflock, LOG_WARNING, MAX_SLAVES, ast_variable::name, ast_variable::next, NULL, sig_pri_chan::resetting, S_OR, sig2str, SIG_PRI_RESET_IDLE, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, tmp(), ast_cli_entry::usage, and ast_variable::value.

◆ dahdi_show_channels()

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

Definition at line 15977 of file chan_dahdi.c.

15978{
15979#define FORMAT "%7s %4d %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"
15980#define FORMAT2 "%7s %4s %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"
15981 ast_group_t targetnum = 0;
15982 int filtertype = 0;
15983 struct dahdi_pvt *tmp = NULL;
15984 char tmps[20];
15985 char blockstr[20];
15986
15987 switch (cmd) {
15988 case CLI_INIT:
15989 e->command = "dahdi show channels [group|context]";
15990 e->usage =
15991 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15992 " Shows a list of available channels with optional filtering\n"
15993 " <group> must be a number between 0 and 63\n";
15994 return NULL;
15995 case CLI_GENERATE:
15996 return NULL;
15997 }
15998
15999 /* syntax: dahdi show channels [ group <group> | context <context> ] */
16000
16001 if (!((a->argc == 3) || (a->argc == 5))) {
16002 return CLI_SHOWUSAGE;
16003 }
16004
16005 if (a->argc == 5) {
16006 if (!strcasecmp(a->argv[3], "group")) {
16007 targetnum = atoi(a->argv[4]);
16008 if (63 < targetnum) {
16009 return CLI_SHOWUSAGE;
16010 }
16011 targetnum = ((ast_group_t) 1) << targetnum;
16012 filtertype = 1;
16013 } else if (!strcasecmp(a->argv[3], "context")) {
16014 filtertype = 2;
16015 }
16016 }
16017
16018 ast_cli(a->fd, FORMAT2, "Chan", "Span", "Signalling", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "In Service", "Alarms", "Description");
16020 for (tmp = iflist; tmp; tmp = tmp->next) {
16021 int alm = 0;
16022 if (filtertype) {
16023 switch(filtertype) {
16024 case 1: /* dahdi show channels group <group> */
16025 if (!(tmp->group & targetnum)) {
16026 continue;
16027 }
16028 break;
16029 case 2: /* dahdi show channels context <context> */
16030 if (strcasecmp(tmp->context, a->argv[4])) {
16031 continue;
16032 }
16033 break;
16034 default:
16035 break;
16036 }
16037 }
16038 if (tmp->channel > 0) {
16039 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
16040 alm = get_alarms(tmp);
16041 } else {
16042 ast_copy_string(tmps, "pseudo", sizeof(tmps));
16043 }
16044
16045 blockstr[0] = tmp->locallyblocked ? 'L' : ' ';
16046 blockstr[1] = tmp->remotelyblocked ? 'R' : ' ';
16047 blockstr[2] = '\0';
16048
16049 ast_cli(a->fd, FORMAT, tmps, tmp->span, sig2str(tmp->sig), tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, tmp->inservice ? "Yes" : "No",
16050 alarm2str(alm), tmp->description);
16051 }
16053 return CLI_SUCCESS;
16054#undef FORMAT
16055#undef FORMAT2
16056}
#define FORMAT
#define FORMAT2
unsigned long long ast_group_t
Definition: channel.h:213

References a, alarm2str(), ast_cli(), ast_copy_string(), ast_mutex_lock, ast_mutex_unlock, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, FORMAT, FORMAT2, get_alarms(), iflist, iflock, NULL, sig2str, tmp(), and ast_cli_entry::usage.

◆ dahdi_show_status()

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

Definition at line 16336 of file chan_dahdi.c.

16337{
16338 #define FORMAT "%4d %-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
16339 #define FORMAT2 "%4s %-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
16340 int span;
16341 int res;
16342 char alarmstr[50];
16343
16344 int ctl;
16345 struct dahdi_spaninfo s;
16346
16347 switch (cmd) {
16348 case CLI_INIT:
16349 e->command = "dahdi show status";
16350 e->usage =
16351 "Usage: dahdi show status\n"
16352 " Shows a list of DAHDI cards with status\n";
16353 return NULL;
16354 case CLI_GENERATE:
16355 return NULL;
16356 }
16357 ctl = open("/dev/dahdi/ctl", O_RDWR);
16358 if (ctl < 0) {
16359 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
16360 return CLI_FAILURE;
16361 }
16362 ast_cli(a->fd, FORMAT2, "Span", "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
16363
16364 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
16365 s.spanno = span;
16366 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
16367 if (res) {
16368 continue;
16369 }
16370 build_alarm_info(alarmstr, &s);
16371 ast_cli(a->fd, FORMAT, span, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
16372 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
16373 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
16374 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
16375 "CAS",
16376 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
16377 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
16378 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
16379 "Unknown",
16380 s.lineconfig & DAHDI_CONFIG_CRC4 ?
16381 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
16382 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
16383 lbostr[s.lbo]
16384 );
16385 }
16386 close(ctl);
16387
16388 return CLI_SUCCESS;
16389#undef FORMAT
16390#undef FORMAT2
16391}

References a, ast_cli(), build_alarm_info(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, errno, FORMAT, FORMAT2, lbostr, NULL, and ast_cli_entry::usage.

◆ dahdi_show_version()

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

Definition at line 16393 of file chan_dahdi.c.

16394{
16395 int pseudo_fd = -1;
16396 struct dahdi_versioninfo vi;
16397
16398 switch (cmd) {
16399 case CLI_INIT:
16400 e->command = "dahdi show version";
16401 e->usage =
16402 "Usage: dahdi show version\n"
16403 " Shows the DAHDI version in use\n";
16404 return NULL;
16405 case CLI_GENERATE:
16406 return NULL;
16407 }
16408 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
16409 ast_cli(a->fd, "Failed to open control file to get version.\n");
16410 return CLI_SUCCESS;
16411 }
16412
16413 strcpy(vi.version, "Unknown");
16414 strcpy(vi.echo_canceller, "Unknown");
16415
16416 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
16417 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
16418 else
16419 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16420
16421 close(pseudo_fd);
16422
16423 return CLI_SUCCESS;
16424}

References a, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, errno, NULL, and ast_cli_entry::usage.

◆ dahdi_sig2str()

static char * dahdi_sig2str ( int  sig)
static

Definition at line 4639 of file chan_dahdi.c.

4640{
4641 static char buf[256];
4642 switch (sig) {
4643 case SIG_EM:
4644 return "E & M Immediate";
4645 case SIG_EMWINK:
4646 return "E & M Wink";
4647 case SIG_EM_E1:
4648 return "E & M E1";
4649 case SIG_FEATD:
4650 return "Feature Group D (DTMF)";
4651 case SIG_FEATDMF:
4652 return "Feature Group D (MF)";
4653 case SIG_FEATDMF_TA:
4654 return "Feature Group D (MF) Tandem Access";
4655 case SIG_FEATB:
4656 return "Feature Group B (MF)";
4657 case SIG_E911:
4658 return "E911 (MF)";
4659 case SIG_FGC_CAMA:
4660 return "FGC/CAMA (Dialpulse)";
4661 case SIG_FGC_CAMAMF:
4662 return "FGC/CAMA (MF)";
4663 case SIG_FXSLS:
4664 return "FXS Loopstart";
4665 case SIG_FXSGS:
4666 return "FXS Groundstart";
4667 case SIG_FXSKS:
4668 return "FXS Kewlstart";
4669 case SIG_FXOLS:
4670 return "FXO Loopstart";
4671 case SIG_FXOGS:
4672 return "FXO Groundstart";
4673 case SIG_FXOKS:
4674 return "FXO Kewlstart";
4675 case SIG_PRI:
4676 return "ISDN PRI";
4677 case SIG_BRI:
4678 return "ISDN BRI Point to Point";
4679 case SIG_BRI_PTMP:
4680 return "ISDN BRI Point to MultiPoint";
4681 case SIG_SS7:
4682 return "SS7";
4683 case SIG_MFCR2:
4684 return "MFC/R2";
4685 case SIG_SF:
4686 return "SF (Tone) Immediate";
4687 case SIG_SFWINK:
4688 return "SF (Tone) Wink";
4689 case SIG_SF_FEATD:
4690 return "SF (Tone) with Feature Group D (DTMF)";
4691 case SIG_SF_FEATDMF:
4692 return "SF (Tone) with Feature Group D (MF)";
4693 case SIG_SF_FEATB:
4694 return "SF (Tone) with Feature Group B (MF)";
4695 case 0:
4696 return "Pseudo";
4697 default:
4698 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
4699 return buf;
4700 }
4701}
#define SIG_BRI
Definition: chan_dahdi.h:801
#define SIG_BRI_PTMP
Definition: chan_dahdi.h:802

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

◆ dahdi_softhangup_all()

static void dahdi_softhangup_all ( void  )
static

Definition at line 15801 of file chan_dahdi.c.

15802{
15803 struct dahdi_pvt *p;
15804retry:
15806 for (p = iflist; p; p = p->next) {
15807 ast_mutex_lock(&p->lock);
15808 if (p->owner && !p->restartpending) {
15809 if (ast_channel_trylock(p->owner)) {
15810 if (DEBUG_ATLEAST(3))
15811 ast_verbose("Avoiding deadlock\n");
15812 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15815 goto retry;
15816 }
15817 if (DEBUG_ATLEAST(3))
15818 ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15820 p->restartpending = 1;
15823 }
15825 }
15827}
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2458
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
#define DEBUG_ATLEAST(level)

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

Referenced by dahdi_restart().

◆ dahdi_train_ec()

static void dahdi_train_ec ( struct dahdi_pvt p)
static

Definition at line 4941 of file chan_dahdi.c.

4942{
4943 int x;
4944 int res;
4945
4946 if (p && p->echocanon && p->echotraining) {
4947 x = p->echotraining;
4948 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
4949 if (res)
4950 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
4951 else
4952 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
4953 } else {
4954 ast_debug(1, "No echo training requested\n");
4955 }
4956}

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

◆ dahdi_wait_event()

static int dahdi_wait_event ( int  fd)
inlinestatic

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 782 of file chan_dahdi.c.

783{
784 int i, j = 0;
785 i = DAHDI_IOMUX_SIGEVENT;
786 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
787 return -1;
788 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
789 return -1;
790 return j;
791}

Referenced by analog_ss_thread(), and my_wait_event().

◆ dahdi_wink()

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

Definition at line 9784 of file chan_dahdi.c.

9785{
9786 int j;
9787 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
9788 for (;;)
9789 {
9790 /* set bits of interest */
9791 j = DAHDI_IOMUX_SIGEVENT;
9792 /* wait for some happening */
9793 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
9794 /* exit loop if we have it */
9795 if (j & DAHDI_IOMUX_SIGEVENT) break;
9796 }
9797 /* get the event info */
9798 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
9799 return 0;
9800}

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

Referenced by analog_ss_thread(), and my_wink().

◆ dahdi_write()

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

Definition at line 9259 of file chan_dahdi.c.

9260{
9261 struct dahdi_pvt *p;
9262 int res;
9263 int idx;
9264
9265 /* Write a frame of (presumably voice) data */
9266 if (frame->frametype != AST_FRAME_VOICE) {
9267 if (frame->frametype != AST_FRAME_IMAGE) {
9268 ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n",
9269 frame->frametype);
9270 }
9271 return 0;
9272 }
9273
9274 /* Return if it's not valid data */
9275 if (!frame->data.ptr || !frame->datalen) {
9276 return 0;
9277 }
9278
9279 p = ast_channel_tech_pvt(ast);
9280 ast_mutex_lock(&p->lock);
9281
9282 idx = dahdi_get_index(ast, p, 0);
9283 if (idx < 0) {
9285 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
9286 return -1;
9287 }
9288
9289 if (p->dialing) {
9291 ast_debug(5, "Dropping frame since I'm still dialing on %s...\n",
9292 ast_channel_name(ast));
9293 return 0;
9294 }
9295 if (!p->owner) {
9297 ast_debug(5, "Dropping frame since there is no active owner on %s...\n",
9298 ast_channel_name(ast));
9299 return 0;
9300 }
9301 if (p->cidspill) {
9303 ast_debug(5, "Dropping frame since I've still got a callerid spill on %s...\n",
9304 ast_channel_name(ast));
9305 return 0;
9306 }
9307
9309 if (!p->subs[idx].linear) {
9310 p->subs[idx].linear = 1;
9311 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9312 if (res)
9313 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
9314 }
9315 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
9318 /* x-law already */
9319 if (p->subs[idx].linear) {
9320 p->subs[idx].linear = 0;
9321 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9322 if (res)
9323 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
9324 }
9325 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
9326 } else {
9328 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n",
9330 return -1;
9331 }
9333 if (res < 0) {
9334 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
9335 return -1;
9336 }
9337 return 0;
9338}
static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
Definition: chan_dahdi.c:9237
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
@ AST_FRAME_IMAGE

References ast_channel_name(), ast_channel_tech_pvt(), ast_debug, ast_format_alaw, ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_get_name(), ast_format_slin, ast_format_ulaw, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log, ast_mutex_lock, ast_mutex_unlock, 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, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_WARNING, my_dahdi_write(), dahdi_pvt::owner, ast_frame::ptr, ast_frame::subclass, and dahdi_pvt::subs.

◆ dahdichannel_to_ami()

static struct ast_manager_event_blob * dahdichannel_to_ami ( struct stasis_message msg)
static

Definition at line 1898 of file chan_dahdi.c.

1899{
1900 RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
1901 struct ast_channel_blob *obj = stasis_message_data(msg);
1902 struct ast_json *group, *span, *channel;
1903
1904 channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1905 if (!channel_string) {
1906 return NULL;
1907 }
1908
1909 group = ast_json_object_get(obj->blob, "group");
1910 span = ast_json_object_get(obj->blob, "span");
1911 channel = ast_json_object_get(obj->blob, "channel");
1912
1913 return ast_manager_event_blob_create(EVENT_FLAG_CALL, "DAHDIChannel",
1914 "%s"
1915 "DAHDIGroup: %llu\r\n"
1916 "DAHDISpan: %u\r\n"
1917 "DAHDIChannel: %s\r\n",
1918 ast_str_buffer(channel_string),
1920 (unsigned int)ast_json_integer_get(span),
1921 ast_json_string_get(channel));
1922}
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition: json.c:332
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Definition: manager.c:10548
#define EVENT_FLAG_CALL
Definition: manager.h:76
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
Blob of data associated with a channel.
struct ast_channel_snapshot * snapshot
struct ast_json * blob
Abstract JSON element (object, array, string, int, ...).

References ast_free, ast_json_integer_get(), ast_json_object_get(), ast_json_string_get(), ast_manager_build_channel_state_string(), ast_manager_event_blob_create(), ast_str_buffer(), ast_channel_blob::blob, EVENT_FLAG_CALL, NULL, RAII_VAR, ast_channel_blob::snapshot, and stasis_message_data().

◆ dahdievent_to_analogevent()

static enum analog_event dahdievent_to_analogevent ( int  event)
static

Definition at line 2594 of file chan_dahdi.c.

2595{
2596 enum analog_event res;
2597
2598 switch (event) {
2599 case DAHDI_EVENT_ONHOOK:
2600 res = ANALOG_EVENT_ONHOOK;
2601 break;
2602 case DAHDI_EVENT_RINGOFFHOOK:
2604 break;
2605 case DAHDI_EVENT_WINKFLASH:
2607 break;
2608 case DAHDI_EVENT_ALARM:
2609 res = ANALOG_EVENT_ALARM;
2610 break;
2611 case DAHDI_EVENT_NOALARM:
2613 break;
2614 case DAHDI_EVENT_DIALCOMPLETE:
2616 break;
2617 case DAHDI_EVENT_RINGERON:
2619 break;
2620 case DAHDI_EVENT_RINGEROFF:
2622 break;
2623 case DAHDI_EVENT_HOOKCOMPLETE:
2625 break;
2626 case DAHDI_EVENT_PULSE_START:
2628 break;
2629 case DAHDI_EVENT_POLARITY:
2631 break;
2632 case DAHDI_EVENT_RINGBEGIN:
2634 break;
2635 case DAHDI_EVENT_EC_DISABLED:
2637 break;
2638 case DAHDI_EVENT_REMOVED:
2640 break;
2641 case DAHDI_EVENT_NEONMWI_ACTIVE:
2643 break;
2644 case DAHDI_EVENT_NEONMWI_INACTIVE:
2646 break;
2647#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
2648 case DAHDI_EVENT_TX_CED_DETECTED:
2650 break;
2651 case DAHDI_EVENT_RX_CED_DETECTED:
2653 break;
2654 case DAHDI_EVENT_EC_NLP_DISABLED:
2656 break;
2657 case DAHDI_EVENT_EC_NLP_ENABLED:
2659 break;
2660#endif
2661 case DAHDI_EVENT_PULSEDIGIT:
2663 break;
2664 case DAHDI_EVENT_DTMFDOWN:
2666 break;
2667 case DAHDI_EVENT_DTMFUP:
2668 res = ANALOG_EVENT_DTMFUP;
2669 break;
2670 default:
2671 switch(event & 0xFFFF0000) {
2672 case DAHDI_EVENT_PULSEDIGIT:
2673 case DAHDI_EVENT_DTMFDOWN:
2674 case DAHDI_EVENT_DTMFUP:
2675 /* The event includes a digit number in the low word.
2676 * Converting it to a 'enum analog_event' would remove
2677 * that information. Thus it is returned as-is.
2678 */
2679 return event;
2680 }
2681
2682 res = ANALOG_EVENT_ERROR;
2683 break;
2684 }
2685
2686 return res;
2687}
analog_event
Definition: sig_analog.h:79
@ ANALOG_EVENT_HOOKCOMPLETE
Definition: sig_analog.h:89
@ ANALOG_EVENT_DTMFDOWN
Definition: sig_analog.h:104
@ ANALOG_EVENT_RINGEROFF
Definition: sig_analog.h:88
@ ANALOG_EVENT_PULSE_START
Definition: sig_analog.h:90
@ ANALOG_EVENT_TX_CED_DETECTED
Definition: sig_analog.h:97
@ ANALOG_EVENT_NEONMWI_ACTIVE
Definition: sig_analog.h:95
@ ANALOG_EVENT_RINGBEGIN
Definition: sig_analog.h:92
@ ANALOG_EVENT_ONHOOK
Definition: sig_analog.h:81
@ ANALOG_EVENT_EC_DISABLED
Definition: sig_analog.h:93
@ ANALOG_EVENT_WINKFLASH
Definition: sig_analog.h:83
@ ANALOG_EVENT_ERROR
Definition: sig_analog.h:101
@ ANALOG_EVENT_PULSEDIGIT
Definition: sig_analog.h:103
@ ANALOG_EVENT_RINGERON
Definition: sig_analog.h:87
@ ANALOG_EVENT_RX_CED_DETECTED
Definition: sig_analog.h:98
@ ANALOG_EVENT_ALARM
Definition: sig_analog.h:84
@ ANALOG_EVENT_DIALCOMPLETE
Definition: sig_analog.h:86
@ ANALOG_EVENT_EC_NLP_ENABLED
Definition: sig_analog.h:100
@ ANALOG_EVENT_POLARITY
Definition: sig_analog.h:91
@ ANALOG_EVENT_NEONMWI_INACTIVE
Definition: sig_analog.h:96
@ ANALOG_EVENT_DTMFUP
Definition: sig_analog.h:105
@ ANALOG_EVENT_EC_NLP_DISABLED
Definition: sig_analog.h:99
@ ANALOG_EVENT_RINGOFFHOOK
Definition: sig_analog.h:82
@ ANALOG_EVENT_REMOVED
Definition: sig_analog.h:94
@ ANALOG_EVENT_NOALARM
Definition: sig_analog.h:85
Definition: astman.c:222

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

◆ dahdisig_to_analogsig()

static enum analog_sigtype dahdisig_to_analogsig ( int  sig)
static

Definition at line 1182 of file chan_dahdi.c.

1183{
1184 switch (sig) {
1185 case SIG_FXOLS:
1186 return ANALOG_SIG_FXOLS;
1187 case SIG_FXOGS:
1188 return ANALOG_SIG_FXOGS;
1189 case SIG_FXOKS:
1190 return ANALOG_SIG_FXOKS;
1191 case SIG_FXSLS:
1192 return ANALOG_SIG_FXSLS;
1193 case SIG_FXSGS:
1194 return ANALOG_SIG_FXSGS;
1195 case SIG_FXSKS:
1196 return ANALOG_SIG_FXSKS;
1197 case SIG_EMWINK:
1198 return ANALOG_SIG_EMWINK;
1199 case SIG_EM:
1200 return ANALOG_SIG_EM;
1201 case SIG_EM_E1:
1202 return ANALOG_SIG_EM_E1;
1203 case SIG_FEATD:
1204 return ANALOG_SIG_FEATD;
1205 case SIG_FEATDMF:
1206 return ANALOG_SIG_FEATDMF;
1207 case SIG_E911:
1208 return SIG_E911;
1209 case SIG_FGC_CAMA:
1210 return ANALOG_SIG_FGC_CAMA;
1211 case SIG_FGC_CAMAMF:
1212 return ANALOG_SIG_FGC_CAMAMF;
1213 case SIG_FEATB:
1214 return ANALOG_SIG_FEATB;
1215 case SIG_SFWINK:
1216 return ANALOG_SIG_SFWINK;
1217 case SIG_SF:
1218 return ANALOG_SIG_SF;
1219 case SIG_SF_FEATD:
1220 return ANALOG_SIG_SF_FEATD;
1221 case SIG_SF_FEATDMF:
1222 return ANALOG_SIG_SF_FEATDMF;
1223 case SIG_FEATDMF_TA:
1224 return ANALOG_SIG_FEATDMF_TA;
1225 case SIG_SF_FEATB:
1226 return ANALOG_SIG_FEATB;
1227 default:
1228 return -1;
1229 }
1230}
@ ANALOG_SIG_FEATD
Definition: sig_analog.h:56
@ ANALOG_SIG_FEATDMF_TA
Definition: sig_analog.h:66
@ ANALOG_SIG_FGC_CAMAMF
Definition: sig_analog.h:60
@ ANALOG_SIG_FXOLS
Definition: sig_analog.h:47
@ ANALOG_SIG_FEATDMF
Definition: sig_analog.h:57
@ ANALOG_SIG_EM_E1
Definition: sig_analog.h:55
@ ANALOG_SIG_EMWINK
Definition: sig_analog.h:53
@ ANALOG_SIG_FXOKS
Definition: sig_analog.h:48
@ ANALOG_SIG_SF
Definition: sig_analog.h:63
@ ANALOG_SIG_FGC_CAMA
Definition: sig_analog.h:59
@ ANALOG_SIG_FXSLS
Definition: sig_analog.h:50
@ ANALOG_SIG_EM
Definition: sig_analog.h:54
@ ANALOG_SIG_FXOGS
Definition: sig_analog.h:49
@ ANALOG_SIG_FXSGS
Definition: sig_analog.h:52
@ ANALOG_SIG_SF_FEATDMF
Definition: sig_analog.h:65
@ ANALOG_SIG_SFWINK
Definition: sig_analog.h:62
@ ANALOG_SIG_FEATB
Definition: sig_analog.h:61
@ ANALOG_SIG_SF_FEATD
Definition: sig_analog.h:64
@ ANALOG_SIG_FXSKS
Definition: sig_analog.h:51

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

◆ deep_copy_dahdi_chan_conf()

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

Definition at line 19922 of file chan_dahdi.c.

19923{
19924 struct ast_cc_config_params *cc_params;
19925
19926 cc_params = dest->chan.cc_params;
19927 *dest = *src;
19928 dest->chan.cc_params = cc_params;
19930}

References ast_cc_copy_config_params(), dahdi_pvt::cc_params, and dahdi_chan_conf::chan.

Referenced by setup_dahdi_int().

◆ destroy_all_channels()

static void destroy_all_channels ( void  )
static

Definition at line 5913 of file chan_dahdi.c.

5914{
5915 int chan;
5916#if defined(HAVE_PRI)
5917 unsigned span;
5918 struct sig_pri_span *pri;
5919#endif /* defined(HAVE_PRI) */
5920 struct dahdi_pvt *p;
5921
5922 while (num_restart_pending) {
5923 usleep(1);
5924 }
5925
5927 /* Destroy all the interfaces and free their memory */
5928 while (iflist) {
5929 p = iflist;
5930
5931 chan = p->channel;
5932#if defined(HAVE_PRI_SERVICE_MESSAGES)
5933 {
5934 char db_chan_name[20];
5935 char db_answer[5];
5936 char state;
5937 int why = -1;
5938
5939 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
5940 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
5941 sscanf(db_answer, "%1c:%30d", &state, &why);
5942 }
5943 if (!why) {
5944 /* SRVST persistence is not required */
5945 ast_db_del(db_chan_name, SRVST_DBKEY);
5946 }
5947 }
5948#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
5949 /* Free associated memory */
5951 ast_verb(3, "Unregistered channel %d\n", chan);
5952 }
5953 ifcount = 0;
5955
5956#if defined(HAVE_PRI)
5957 /* Destroy all of the no B channel interface lists */
5958 for (span = 0; span < NUM_SPANS; ++span) {
5959 if (!pris[span].dchannels[0]) {
5960 break;
5961 }
5962 pri = &pris[span].pri;
5963 ast_mutex_lock(&pri->lock);
5964 while (pri->no_b_chan_iflist) {
5965 p = pri->no_b_chan_iflist;
5966
5967 /* Free associated memory */
5969 }
5970 ast_mutex_unlock(&pri->lock);
5971 }
5972#endif /* defined(HAVE_PRI) */
5973}
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: main/db.c:427
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:476
enum cc_state state
Definition: ccss.c:393
static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5815
static int ifcount
Definition: chan_dahdi.c:749
struct pri * pri
Definition: sig_pri.h:602
void * no_b_chan_iflist
Definition: sig_pri.h:607
ast_mutex_t lock
Definition: sig_pri.h:616

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

Referenced by __unload_module(), and dahdi_restart().

◆ destroy_channel()

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

Definition at line 5895 of file chan_dahdi.c.

5896{
5897 int i;
5898
5899 if (!now) {
5900 /* Do not destroy the channel now if it is owned by someone. */
5901 if (cur->owner) {
5902 return;
5903 }
5904 for (i = 0; i < 3; i++) {
5905 if (cur->subs[i].owner) {
5906 return;
5907 }
5908 }
5909 }
5910 destroy_dahdi_pvt(cur);
5911}

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

Referenced by dahdi_destroy_channel_range(), and dahdi_hangup().

◆ destroy_dahdi_pvt()

static void destroy_dahdi_pvt ( struct dahdi_pvt pvt)
static

Definition at line 5815 of file chan_dahdi.c.

5816{
5817 struct dahdi_pvt *p = pvt;
5818
5819 if (p->manages_span_alarms) {
5821 if (next) {
5823 }
5824 }
5825
5826 /* Remove channel from the list */
5827#if defined(HAVE_PRI)
5828 dahdi_unlink_pri_pvt(p);
5829#endif /* defined(HAVE_PRI) */
5830#if defined(HAVE_SS7)
5831 dahdi_unlink_ss7_pvt(p);
5832#endif /* defined(HAVE_SS7) */
5833#if defined(HAVE_OPENR2)
5834 dahdi_unlink_mfcr2_pvt(p);
5835#endif /* defined(HAVE_SS7) */
5836 switch (pvt->which_iflist) {
5837 case DAHDI_IFLIST_NONE:
5838 break;
5839 case DAHDI_IFLIST_MAIN:
5841 break;
5842#if defined(HAVE_PRI)
5843 case DAHDI_IFLIST_NO_B_CHAN:
5844 if (p->pri) {
5845 dahdi_nobch_extract(p->pri, p);
5846 }
5847 break;
5848#endif /* defined(HAVE_PRI) */
5849 }
5850
5851 if (p->sig_pvt) {
5852 if (dahdi_analog_lib_handles(p->sig, 0, 0)) {
5854 }
5855 switch (p->sig) {
5856#if defined(HAVE_PRI)
5859 break;
5860#endif /* defined(HAVE_PRI) */
5861#if defined(HAVE_SS7)
5862 case SIG_SS7:
5864 break;
5865#endif /* defined(HAVE_SS7) */
5866 default:
5867 break;
5868 }
5869 }
5870 ast_free(p->cidspill);
5871 if (p->use_smdi) {
5873 }
5874 if (p->mwi_event_sub) {
5876 }
5877 if (p->vars) {
5879 }
5880 if (p->cc_params) {
5882 }
5883
5886
5889 if (p->owner) {
5891 }
5892 ast_free(p);
5893}
static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5588
static struct dahdi_pvt * find_next_iface_in_span(struct dahdi_pvt *cur)
Definition: chan_dahdi.c:5804
struct ast_namedgroups * ast_unref_namedgroups(struct ast_namedgroups *groups)
Definition: channel.c:7732
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
#define ast_mutex_destroy(a)
Definition: lock.h:188
void * ast_mwi_unsubscribe(struct ast_mwi_subscriber *sub)
Unsubscribe from the stasis topic and MWI.
Definition: mwi.c:254
void analog_delete(struct analog_pvt *doomed)
Delete the analog private structure.
Definition: sig_analog.c:4104
void sig_pri_chan_delete(struct sig_pri_chan *doomed)
void sig_ss7_chan_delete(struct sig_ss7_chan *doomed)
struct ast_mwi_subscriber * mwi_event_sub
Opaque event subscription parameters for message waiting indication support.
Definition: chan_dahdi.h:711
unsigned int manages_span_alarms
TRUE if the channel alarms will be managed also as Span ones.
Definition: chan_dahdi.h:465

References analog_delete(), ao2_cleanup, ast_cc_config_params_destroy(), ast_channel_tech_pvt_set(), ast_free, ast_mutex_destroy, ast_mwi_unsubscribe(), ast_unref_namedgroups(), ast_variables_destroy(), dahdi_pvt::cc_params, dahdi_pvt::cidspill, dahdi_analog_lib_handles(), 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::named_callgroups, dahdi_pvt::named_pickupgroups, dahdi_pvt::next, NULL, 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, dahdi_pvt::use_smdi, dahdi_pvt::vars, and dahdi_pvt::which_iflist.

Referenced by destroy_all_channels(), destroy_channel(), duplicate_pseudo(), and mkintf().

◆ determine_starting_point()

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

Definition at line 13730 of file chan_dahdi.c.

13731{
13732 char *dest;
13733 char *s;
13734 int x;
13735 int res = 0;
13736 struct dahdi_pvt *p;
13737 char *subdir = NULL;
13739 AST_APP_ARG(group); /* channel/group token */
13740 //AST_APP_ARG(ext); /* extension token */
13741 //AST_APP_ARG(opts); /* options token */
13742 AST_APP_ARG(other); /* Any remining unused arguments */
13743 );
13744
13745 /*
13746 * data is ---v
13747 * Dial(DAHDI/pseudo[/extension[/options]])
13748 * Dial(DAHDI/<channel#>[c|r<cadence#>|d][/extension[/options]])
13749 * Dial(DAHDI/<subdir>!<channel#>[c|r<cadence#>|d][/extension[/options]])
13750 * Dial(DAHDI/i<span>[/extension[/options]])
13751 * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadence#>|d][/extension[/options]])
13752 *
13753 * i - ISDN span channel restriction.
13754 * Used by CC to ensure that the CC recall goes out the same span.
13755 * Also to make ISDN channel names dialable when the sequence number
13756 * is stripped off. (Used by DTMF attended transfer feature.)
13757 *
13758 * g - channel group allocation search forward
13759 * G - channel group allocation search backward
13760 * r - channel group allocation round robin search forward
13761 * R - channel group allocation round robin search backward
13762 *
13763 * c - Wait for DTMF digit to confirm answer
13764 * r<cadence#> - Set distinctive ring cadence number
13765 * d - Force bearer capability for ISDN/SS7 call to digital.
13766 */
13767
13768 if (data) {
13769 dest = ast_strdupa(data);
13770 } else {
13771 ast_log(LOG_WARNING, "Channel requested with no data\n");
13772 return NULL;
13773 }
13774 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13775 if (!args.argc || ast_strlen_zero(args.group)) {
13776 ast_log(LOG_WARNING, "No channel/group specified\n");
13777 return NULL;
13778 }
13779
13780 /* Initialize the output parameters */
13781 memset(param, 0, sizeof(*param));
13782 param->channelmatch = -1;
13783
13784 if (strchr(args.group, '!') != NULL) {
13785 char *prev = args.group;
13786 while ((s = strchr(prev, '!')) != NULL) {
13787 *s++ = '/';
13788 prev = s;
13789 }
13790 *(prev - 1) = '\0';
13791 subdir = args.group;
13792 args.group = prev;
13793 } else if (args.group[0] == 'i') {
13794 /* Extract the ISDN span channel restriction specifier. */
13795 res = sscanf(args.group + 1, "%30d", &x);
13796 if (res < 1) {
13797 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13798 return NULL;
13799 }
13800 param->span = x;
13801
13802 /* Remove the ISDN span channel restriction specifier. */
13803 s = strchr(args.group, '-');
13804 if (!s) {
13805 /* Search all groups since we are ISDN span restricted. */
13806 return iflist;
13807 }
13808 args.group = s + 1;
13809 res = 0;
13810 }
13811 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13812 /* Retrieve the group number */
13813 s = args.group + 1;
13814 res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadence);
13815 if (res < 1) {
13816 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13817 return NULL;
13818 }
13819 param->groupmatch = ((ast_group_t) 1 << x);
13820
13821 if (toupper(args.group[0]) == 'G') {
13822 if (args.group[0] == 'G') {
13823 param->backwards = 1;
13824 p = ifend;
13825 } else
13826 p = iflist;
13827 } else {
13828 if (ARRAY_LEN(round_robin) <= x) {
13829 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13830 x, data);
13831 return NULL;
13832 }
13833 if (args.group[0] == 'R') {
13834 param->backwards = 1;
13835 p = round_robin[x] ? round_robin[x]->prev : ifend;
13836 if (!p)
13837 p = ifend;
13838 } else {
13839 p = round_robin[x] ? round_robin[x]->next : iflist;
13840 if (!p)
13841 p = iflist;
13842 }
13843 param->roundrobin = 1;
13844 param->rr_starting_point = x;
13845 }
13846 } else {
13847 s = args.group;
13848 if (!strcasecmp(s, "pseudo")) {
13849 /* Special case for pseudo */
13850 x = CHAN_PSEUDO;
13851 param->channelmatch = x;
13852 } else {
13853 res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadence);
13854 if (res < 1) {
13855 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13856 return NULL;
13857 } else {
13858 param->channelmatch = x;
13859 }
13860 }
13861 if (subdir) {
13862 char path[PATH_MAX];
13863 struct stat stbuf;
13864
13865 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13866 subdir, param->channelmatch);
13867 if (stat(path, &stbuf) < 0) {
13868 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13869 path, strerror(errno));
13870 return NULL;
13871 }
13872 if (!S_ISCHR(stbuf.st_mode)) {
13873 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13874 path);
13875 return NULL;
13876 }
13877 param->channelmatch = minor(stbuf.st_rdev);
13878 }
13879
13880 p = iflist;
13881 }
13882
13883 if (param->opt == 'r' && res < 3) {
13884 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13885 param->opt = '\0';
13886 }
13887
13888 return p;
13889}
#define PATH_MAX
Definition: asterisk.h:40
ast_group_t groupmatch
Definition: chan_dahdi.c:13714

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::cadence, CHAN_PSEUDO, dahdi_starting_point::channelmatch, errno, dahdi_starting_point::groupmatch, ifend, iflist, LOG_ERROR, LOG_WARNING, dahdi_pvt::next, NULL, dahdi_starting_point::opt, PATH_MAX, dahdi_pvt::prev, round_robin, dahdi_starting_point::roundrobin, dahdi_starting_point::rr_starting_point, and dahdi_starting_point::span.

Referenced by dahdi_cc_callback(), and dahdi_request().

◆ digit_to_dtmfindex()

static int digit_to_dtmfindex ( char  digit)
static

Definition at line 4469 of file chan_dahdi.c.

4470{
4471 if (isdigit(digit))
4472 return DAHDI_TONE_DTMF_BASE + (digit - '0');
4473 else if (digit >= 'A' && digit <= 'D')
4474 return DAHDI_TONE_DTMF_A + (digit - 'A');
4475 else if (digit >= 'a' && digit <= 'd')
4476 return DAHDI_TONE_DTMF_A + (digit - 'a');
4477 else if (digit == '*')
4478 return DAHDI_TONE_DTMF_s;
4479 else if (digit == '#')
4480 return DAHDI_TONE_DTMF_p;
4481 else
4482 return -1;
4483}

References digit.

Referenced by dahdi_digit_begin().

◆ do_monitor()

static void * do_monitor ( void *  data)
static

Definition at line 11847 of file chan_dahdi.c.

11848{
11849 int count, res, res2, spoint, pollres=0;
11850 struct dahdi_pvt *i;
11851 struct dahdi_pvt *last = NULL;
11852 struct dahdi_pvt *doomed;
11853 time_t thispass = 0, lastpass = 0;
11854 int found;
11855 char buf[1024];
11856 struct pollfd *pfds=NULL;
11857 int lastalloc = -1;
11858 /* This thread monitors all the frame relay interfaces which are not yet in use
11859 (and thus do not have a separate thread) indefinitely */
11860 /* From here on out, we die whenever asked */
11861#if 0
11862 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11863 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11864 return NULL;
11865 }
11866 ast_debug(1, "Monitor starting...\n");
11867#endif
11868 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11869
11870 pthread_cleanup_push(monitor_pfds_clean, &pfds);
11871 for (;;) {
11872 /* Lock the interface list */
11874 if (!pfds || (lastalloc != ifcount)) {
11875 if (pfds) {
11876 ast_free(pfds);
11877 pfds = NULL;
11878 }
11879 if (ifcount) {
11880 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11882 return NULL;
11883 }
11884 }
11885 lastalloc = ifcount;
11886 }
11887 /* Build the stuff we're going to poll on, that is the socket of every
11888 dahdi_pvt that does not have an associated owner channel */
11889 count = 0;
11890 for (i = iflist; i; i = i->next) {
11891 ast_mutex_lock(&i->lock);
11892 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11893 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11894 struct analog_pvt *p = i->sig_pvt;
11895
11896 if (!p) {
11897 ast_log(LOG_ERROR, "No sig_pvt?\n");
11898 } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11899 /* This needs to be watched, as it lacks an owner */
11900 pfds[count].fd = i->subs[SUB_REAL].dfd;
11901 pfds[count].events = POLLPRI;
11902 pfds[count].revents = 0;
11903 /* Message waiting or r2 channels also get watched for reading */
11904 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11905 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11906 pfds[count].events |= POLLIN;
11907 }
11908 count++;
11909 }
11910 } else {
11911 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11912 /* This needs to be watched, as it lacks an owner */
11913 pfds[count].fd = i->subs[SUB_REAL].dfd;
11914 pfds[count].events = POLLPRI;
11915 pfds[count].revents = 0;
11916 /* If we are monitoring for VMWI or sending CID, we need to
11917 read from the channel as well */
11918 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11919 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11920 pfds[count].events |= POLLIN;
11921 }
11922 count++;
11923 }
11924 }
11925 }
11927 }
11928 /* Okay, now that we know what to do, release the interface lock */
11930
11931 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11932 pthread_testcancel();
11933 /* Wait at least a second for something to happen */
11934 res = poll(pfds, count, 1000);
11935 pthread_testcancel();
11936 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11937
11938 /* Okay, poll has finished. Let's see what happened. */
11939 if (res < 0) {
11940 if ((errno != EAGAIN) && (errno != EINTR))
11941 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11942 continue;
11943 }
11944 /* Alright, lock the interface list again, and let's look and see what has
11945 happened */
11947 found = 0;
11948 spoint = 0;
11949 lastpass = thispass;
11950 thispass = time(NULL);
11951 doomed = NULL;
11952 for (i = iflist;; i = i->next) {
11953 if (doomed) {
11955 doomed = NULL;
11956 }
11957 if (!i) {
11958 break;
11959 }
11960
11961 if (thispass != lastpass) {
11962 if (!found && ((i == last) || ((i == iflist) && !last))) {
11963 last = i;
11964 if (last) {
11965 struct analog_pvt *analog_p = last->sig_pvt;
11966 /* Only allow MWI to be initiated on a quiescent fxs port */
11967 if (analog_p
11968 && !last->mwisendactive
11969 && (last->sig & __DAHDI_SIG_FXO)
11970 && !analog_p->fxsoffhookstate
11971 && !last->owner
11972 && (!ast_strlen_zero(last->mailbox) || last->mwioverride_active)
11973 && !analog_p->subs[SUB_REAL].owner /* could be a recall ring from a flash hook hold */
11974 && (thispass - analog_p->onhooktime > 3)) {
11975 res = has_voicemail(last);
11976 if (analog_p->msgstate != res) {
11977 /* Set driver resources for signalling VMWI */
11978 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11979 if (res2) {
11980 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11981 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11982 }
11983 /* If enabled for FSK spill then initiate it */
11984 if (mwi_send_init(last)) {
11985 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11986 }
11987 analog_p->msgstate = res;
11988 found ++;
11989 }
11990 }
11991 last = last->next;
11992 }
11993 }
11994 }
11995 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11996 if (i->radio && !i->owner)
11997 {
11998 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11999 if (res)
12000 {
12001 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
12002 /* Don't hold iflock while handling init events */
12004 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
12006 else
12007 doomed = handle_init_event(i, res);
12009 }
12010 continue;
12011 }
12012 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
12013 if (pollres & POLLIN) {
12014 if (i->owner || i->subs[SUB_REAL].owner) {
12015#ifdef HAVE_PRI
12016 if (!i->pri)
12017#endif
12018 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
12019 continue;
12020 }
12022 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
12023 continue;
12024 }
12025 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
12026 if (res > 0) {
12027 if (i->mwimonitor_fsk) {
12028 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
12029 pthread_attr_t attr;
12030 pthread_t threadid;
12031 struct mwi_thread_data *mtd;
12032
12033 pthread_attr_init(&attr);
12034 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
12035
12036 ast_debug(1, "Maybe some MWI on port %d!\n", i->channel);
12037 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
12038 mtd->pvt = i;
12039 memcpy(mtd->buf, buf, res);
12040 mtd->len = res;
12041 i->mwimonitoractive = 1;
12042 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
12043 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
12044 i->mwimonitoractive = 0;
12045 ast_free(mtd);
12046 }
12047 }
12048 }
12049 /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
12050 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
12051 int energy;
12052 struct timeval now;
12053 /* State machine dtmfcid_holdoff_state allows for the line to settle
12054 * before checking agin for dtmf energy. Presently waits for 500 mS before checking again
12055 */
12056 if (1 == i->dtmfcid_holdoff_state) {
12057 gettimeofday(&i->dtmfcid_delay, NULL);
12058 i->dtmfcid_holdoff_state = 2;
12059 } else if (2 == i->dtmfcid_holdoff_state) {
12060 gettimeofday(&now, NULL);
12061 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
12062 i->dtmfcid_holdoff_state = 0;
12063 }
12064 } else {
12065 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
12066 if (!i->mwisendactive && energy > dtmfcid_level) {
12067 pthread_t threadid;
12068 struct ast_channel *chan;
12070 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12071 /* just in case this event changes or somehow destroys a channel, set doomed here too */
12073 i->dtmfcid_holdoff_state = 1;
12074 } else {
12075 ast_callid callid = 0;
12076 int callid_created = ast_callid_threadstorage_auto(&callid);
12077 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
12078 if (!chan) {
12079 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
12080 } else {
12081 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
12082 if (res) {
12083 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
12084 ast_hangup(chan);
12085 } else {
12086 i->dtmfcid_holdoff_state = 1;
12087 }
12088 }
12090 }
12092 }
12093 }
12094 }
12095 if (i->mwisendactive) {
12097 }
12098 } else {
12099 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
12100 }
12101 }
12102 if (pollres & POLLPRI) {
12103 if (i->owner || i->subs[SUB_REAL].owner) {
12104#ifdef HAVE_PRI
12105 if (!i->pri)
12106#endif
12107 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
12108 continue;
12109 }
12110 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12111 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
12112 /* Don't hold iflock while handling init events */
12114 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
12115 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
12117 else
12118 doomed = handle_init_event(i, res);
12119 }
12120 if (i->doreoriginate && res == DAHDI_EVENT_HOOKCOMPLETE) {
12121 /* Actually automatically reoriginate this FXS line, if directed to.
12122 * We should get a DAHDI_EVENT_HOOKCOMPLETE from the loop disconnect
12123 * doing its thing (one reason why this is for FXOKS only: FXOLS
12124 * hangups don't give us any DAHDI events to piggyback off of)*/
12125 i->doreoriginate = 0;
12126 /* Double check the channel is still off-hook. There's only about a millisecond
12127 * between when doreoriginate is set high and we see that here, but just to be safe. */
12128 if (!my_is_off_hook(i)) {
12129 ast_debug(1, "Woah! Went back on hook before reoriginate could happen on channel %d\n", i->channel);
12130 } else {
12131 ast_verb(3, "Automatic reorigination on channel %d\n", i->channel);
12132 res = DAHDI_EVENT_RINGOFFHOOK; /* Pretend that the physical channel just went off hook */
12133 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12135 } else {
12136 doomed = handle_init_event(i, res);
12137 }
12138 }
12139 }
12141 }
12142 }
12143 }
12146#ifdef HAVE_OPENR2
12147 dahdi_r2_destroy_nodev();
12148#endif
12149 }
12150 /* Never reached */
12151 pthread_cleanup_pop(1);
12152 return NULL;
12153
12154}
struct sla_ringing_trunk * last
Definition: app_sla.c:332
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
static int calc_energy(const unsigned char *buf, int len, struct ast_format *law)
Definition: chan_dahdi.c:11077
static void release_doomed_pris(void)
Definition: chan_dahdi.c:1283
static enum analog_event dahdievent_to_analogevent(int event)
Definition: chan_dahdi.c:2594
static int mwi_send_init(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:11248
static void * mwi_thread(void *data)
Definition: chan_dahdi.c:11091
static int mwilevel
Definition: chan_dahdi.c:733
static int mwi_send_process_buffer(struct dahdi_pvt *pvt, int num_read)
Definition: chan_dahdi.c:11301
static int dtmfcid_level
Definition: chan_dahdi.c:734
static int mwi_send_process_event(struct dahdi_pvt *pvt, int event)
Definition: chan_dahdi.c:11389
static struct dahdi_pvt * handle_init_event(struct dahdi_pvt *i, int event)
Definition: chan_dahdi.c:11583
static void monitor_pfds_clean(void *arg)
Definition: chan_dahdi.c:11842
static int ast_fdisset(struct pollfd *pfds, int fd, int maximum, int *start)
Helper function for migrating select to poll.
Definition: channel.h:2827
void * analog_handle_init_event(struct analog_pvt *i, int event)
Definition: sig_analog.c:3793
@ ANALOG_EVENT_DTMFCID
Definition: sig_analog.h:102
int msgstate
-1 = unknown, 0 = no messages, 1 = new messages available
Definition: sig_analog.h:284
int onhooktime
Definition: sig_analog.h:281
struct ast_channel * owner
Definition: sig_analog.h:277
struct analog_subchannel subs[3]
Definition: sig_analog.h:279
struct ast_channel * owner
Definition: sig_analog.h:264
struct timeval dtmfcid_delay
Definition: chan_dahdi.h:591
unsigned int mwisendactive
TRUE if a MWI message sending thread is active.
Definition: chan_dahdi.h:433
unsigned int mwimonitoractive
TRUE if an MWI monitor thread is currently active.
Definition: chan_dahdi.h:431
int dtmfcid_holdoff_state
Definition: chan_dahdi.h:590
unsigned int mwimonitor_fsk
TRUE if the FXO port monitors for fsk type MWI indications from the other end.
Definition: chan_dahdi.h:423
struct dahdi_pvt * pvt
Definition: chan_dahdi.c:11072
unsigned char buf[READ_SIZE]
Definition: chan_dahdi.c:11073
struct sla_ringing_trunk * next
Definition: app_sla.c:308
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592

References ANALOG_EVENT_DTMFCID, analog_handle_init_event(), analog_ss_thread(), ast_callid_threadstorage_auto(), ast_callid_threadstorage_auto_clean(), ast_calloc, ast_debug, ast_fdisset(), ast_free, ast_hangup(), AST_LAW, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, ast_pthread_create_detached, AST_STATE_PRERING, ast_strlen_zero(), ast_verb, buf, mwi_thread_data::buf, calc_energy(), ast_channel::callid, dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, dahdi_pvt::cidspill, dahdi_analog_lib_handles(), dahdi_destroy_channel_range(), dahdi_get_event(), dahdi_new(), dahdievent_to_analogevent(), dahdi_subchannel::dfd, dahdi_pvt::doreoriginate, dahdi_pvt::dtmfcid_delay, dahdi_pvt::dtmfcid_holdoff_state, dtmfcid_level, errno, event2str(), analog_pvt::fxsoffhookstate, handle_init_event(), has_voicemail(), ifcount, iflist, iflock, last, mwi_thread_data::len, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, monitor_pfds_clean(), analog_pvt::msgstate, mwi_send_init(), mwi_send_process_buffer(), mwi_send_process_event(), mwi_thread(), mwilevel, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitoractive, dahdi_pvt::mwisendactive, my_is_off_hook(), sla_ringing_trunk::next, dahdi_pvt::next, NULL, 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, release_doomed_pris(), dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, dahdi_pvt::sig_pvt, SUB_REAL, dahdi_pvt::subs, and analog_pvt::subs.

Referenced by restart_monitor().

◆ drc_sample()

static int drc_sample ( int  sample,
float  drc 
)
static

Definition at line 4986 of file chan_dahdi.c.

4987{
4988 float neg;
4989 float shallow, steep;
4990 float max = SHRT_MAX;
4991
4992 neg = (sample < 0 ? -1 : 1);
4993 steep = drc*sample;
4994 shallow = neg*(max-max/drc)+(float)sample/drc;
4995 if (fabsf(steep) < fabsf(shallow)) {
4996 sample = steep;
4997 }
4998 else {
4999 sample = shallow;
5000 }
5001
5002 return sample;
5003}
#define max(a, b)
Definition: f2c.h:198

References max.

Referenced by fill_rxgain(), and fill_txgain().

◆ duplicate_pseudo()

static struct dahdi_pvt * duplicate_pseudo ( struct dahdi_pvt src)
static

Definition at line 13666 of file chan_dahdi.c.

13667{
13668 struct dahdi_pvt *p;
13669 struct dahdi_bufferinfo bi;
13670 int res;
13671
13672 p = ast_malloc(sizeof(*p));
13673 if (!p) {
13674 return NULL;
13675 }
13676 *p = *src;
13677
13678 /* Must deep copy the cc_params. */
13680 if (!p->cc_params) {
13681 ast_free(p);
13682 return NULL;
13683 }
13685
13687 p->next = NULL;
13688 p->prev = NULL;
13689 ast_mutex_init(&p->lock);
13690 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13691 if (p->subs[SUB_REAL].dfd < 0) {
13692 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13694 return NULL;
13695 }
13696 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13697 if (!res) {
13698 bi.txbufpolicy = src->buf_policy;
13699 bi.rxbufpolicy = src->buf_policy;
13700 bi.numbufs = src->buf_no;
13701 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13702 if (res < 0) {
13703 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13704 }
13705 } else
13706 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13707 p->destroy = 1;
13709 return p;
13710}
static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5540
#define ast_mutex_init(pmutex)
Definition: lock.h:186

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, NULL, dahdi_pvt::prev, SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::which_iflist.

Referenced by dahdi_request().

◆ event2str()

static const char * event2str ( int  event)
static

Definition at line 4630 of file chan_dahdi.c.

4631{
4632 static char buf[256];
4633 if ((event > -1) && (event < (ARRAY_LEN(events))) )
4634 return events[event];
4635 sprintf(buf, "Event %d", event); /* safe */
4636 return buf;
4637}
static const char *const events[]
Definition: chan_dahdi.c:4585

References ARRAY_LEN, buf, and events.

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

◆ fill_rxgain()

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

Definition at line 5056 of file chan_dahdi.c.

5057{
5058 int j;
5059 int k;
5060 float linear_gain = pow(10.0, gain / 20.0);
5061
5062 switch (law) {
5063 case DAHDI_LAW_ALAW:
5064 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5065 if (gain || drc) {
5066 k = AST_ALAW(j);
5067 if (drc) {
5068 k = drc_sample(k, drc);
5069 }
5070 k = (float)k * linear_gain;
5071 if (k > 32767) {
5072 k = 32767;
5073 } else if (k < -32768) {
5074 k = -32768;
5075 }
5076 g->rxgain[j] = AST_LIN2A(k);
5077 } else {
5078 g->rxgain[j] = j;
5079 }
5080 }
5081 break;
5082 case DAHDI_LAW_MULAW:
5083 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5084 if (gain || drc) {
5085 k = AST_MULAW(j);
5086 if (drc) {
5087 k = drc_sample(k, drc);
5088 }
5089 k = (float)k * linear_gain;
5090 if (k > 32767) {
5091 k = 32767;
5092 } else if (k < -32768) {
5093 k = -32768;
5094 }
5095 g->rxgain[j] = AST_LIN2MU(k);
5096 } else {
5097 g->rxgain[j] = j;
5098 }
5099 }
5100 break;
5101 }
5102}
#define AST_LIN2A(a)
Definition: alaw.h:50
static int drc_sample(int sample, float drc)
Definition: chan_dahdi.c:4986
#define AST_LIN2MU(a)
Definition: ulaw.h:49

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

Referenced by set_actual_rxgain().

◆ fill_txgain()

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

Definition at line 5006 of file chan_dahdi.c.

5007{
5008 int j;
5009 int k;
5010
5011 float linear_gain = pow(10.0, gain / 20.0);
5012
5013 switch (law) {
5014 case DAHDI_LAW_ALAW:
5015 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
5016 if (gain || drc) {
5017 k = AST_ALAW(j);
5018 if (drc) {
5019 k = drc_sample(k, drc);
5020 }
5021 k = (float)k * linear_gain;
5022 if (k > 32767) {
5023 k = 32767;
5024 } else if (k < -32768) {
5025 k = -32768;
5026 }
5027 g->txgain[j] = AST_LIN2A(k);
5028 } else {
5029 g->txgain[j] = j;
5030 }
5031 }
5032 break;
5033 case DAHDI_LAW_MULAW:
5034 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
5035 if (gain || drc) {
5036 k = AST_MULAW(j);
5037 if (drc) {
5038 k = drc_sample(k, drc);
5039 }
5040 k = (float)k * linear_gain;
5041 if (k > 32767) {
5042 k = 32767;
5043 } else if (k < -32768) {
5044 k = -32768;
5045 }
5046 g->txgain[j] = AST_LIN2MU(k);
5047
5048 } else {
5049 g->txgain[j] = j;
5050 }
5051 }
5052 break;
5053 }
5054}

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

Referenced by set_actual_txgain().

◆ find_channel()

static struct dahdi_pvt * find_channel ( int  channel)
static

Definition at line 16743 of file chan_dahdi.c.

16744{
16745 struct dahdi_pvt *p;
16746
16748 for (p = iflist; p; p = p->next) {
16749 if (p->channel == channel) {
16750 break;
16751 }
16752 }
16754 return p;
16755}

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

Referenced by find_channel_from_str().

◆ find_channel_from_str()

static struct dahdi_pvt * find_channel_from_str ( const char *  channel)
static

Definition at line 16766 of file chan_dahdi.c.

16767{
16768 int chan_num;
16769
16770 if (sscanf(channel, "%30d", &chan_num) != 1) {
16771 /* Not numeric string. */
16772 return NULL;
16773 }
16774
16775 return find_channel(chan_num);
16776}
static struct dahdi_pvt * find_channel(int channel)
Definition: chan_dahdi.c:16743

References dahdi_pvt::channel, find_channel(), and NULL.

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

◆ find_next_iface_in_span()

static struct dahdi_pvt * find_next_iface_in_span ( struct dahdi_pvt cur)
static

Definition at line 5804 of file chan_dahdi.c.

5805{
5806 if (cur->next && cur->next->span == cur->span) {
5807 return cur->next;
5808 } else if (cur->prev && cur->prev->span == cur->span) {
5809 return cur->prev;
5810 }
5811
5812 return NULL;
5813}

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

Referenced by destroy_dahdi_pvt().

◆ fxo_pvt()

static struct dahdi_pvt * fxo_pvt ( struct ast_channel chan)
static

Return DAHDI pivot if channel is FXO signalled.

Definition at line 2830 of file chan_dahdi.c.

2831{
2832 int res;
2833 struct dahdi_params dahdip;
2834 struct dahdi_pvt *pvt = NULL;
2835
2836 if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
2837 ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", ast_channel_name(chan));
2838 return NULL;
2839 }
2840
2841 memset(&dahdip, 0, sizeof(dahdip));
2842 res = ioctl(ast_channel_fd(chan, 0), DAHDI_GET_PARAMS, &dahdip);
2843
2844 if (res) {
2845 ast_log(LOG_WARNING, "Unable to get parameters of %s: %s\n", ast_channel_name(chan), strerror(errno));
2846 return NULL;
2847 }
2848 if (!(dahdip.sigtype & __DAHDI_SIG_FXO)) {
2849 ast_log(LOG_WARNING, "%s is not FXO signalled\n", ast_channel_name(chan));
2850 return NULL;
2851 }
2852
2853 pvt = ast_channel_tech_pvt(chan);
2854 if (!dahdi_analog_lib_handles(pvt->sig, 0, 0)) {
2855 ast_log(LOG_WARNING, "Channel signalling is not analog");
2856 return NULL;
2857 }
2858
2859 return pvt;
2860}

References ast_channel_fd(), ast_channel_name(), ast_channel_tech(), ast_channel_tech_pvt(), ast_log, dahdi_analog_lib_handles(), errno, LOG_WARNING, NULL, dahdi_pvt::sig, and type.

Referenced by polarity_read(), and polarity_write().

◆ gen_pvt_field_callback() [1/3]

gen_pvt_field_callback ( int  ,
firstdigit_timeout   
)

◆ gen_pvt_field_callback() [2/3]

gen_pvt_field_callback ( int  ,
interdigit_timeout   
)

◆ gen_pvt_field_callback() [3/3]

gen_pvt_field_callback ( int  ,
matchdigit_timeout   
)

◆ get_alarms()

static int get_alarms ( struct dahdi_pvt p)
static

Checks channel for alarms

Parameters
pa 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 7555 of file chan_dahdi.c.

7556{
7557 int res;
7558 struct dahdi_spaninfo zi;
7559 struct dahdi_params params;
7560
7561 memset(&zi, 0, sizeof(zi));
7562 zi.spanno = p->span;
7563
7564 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
7565 if (zi.alarms != DAHDI_ALARM_NONE)
7566 return zi.alarms;
7567 } else {
7568 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
7569 return 0;
7570 }
7571
7572 /* No alarms on the span. Check for channel alarms. */
7573 memset(&params, 0, sizeof(params));
7574 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
7575 return params.chan_alarms;
7576
7577 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
7578
7579 return DAHDI_ALARM_NONE;
7580}

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(), dahdi_show_channels(), handle_init_event(), mkintf(), mwi_thread(), and my_get_and_handle_alarms().

◆ handle_alarms()

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

Definition at line 7715 of file chan_dahdi.c.

7716{
7717 const char *alarm_str;
7718
7719#if defined(HAVE_PRI)
7721 return;
7722 }
7723#endif /* defined(HAVE_PRI) */
7724
7725 alarm_str = alarm2str(alms);
7727 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
7728 publish_channel_alarm(p->channel, alarm_str);
7729 }
7730
7732 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
7733 publish_span_alarm(p->span, alarm_str);
7734 }
7735}
static void publish_channel_alarm(int channel, const char *alarm_txt)
Definition: chan_dahdi.c:7696
static void publish_span_alarm(int span, const char *alarm_txt)
Definition: chan_dahdi.c:7682
static int report_alarms
Definition: chan_dahdi.c:738
#define REPORT_CHANNEL_ALARMS
Definition: chan_dahdi.c:736
#define REPORT_SPAN_ALARMS
Definition: chan_dahdi.c:737
int sig_pri_is_alarm_ignored(struct sig_pri_span *pri)

References alarm2str(), ast_log, dahdi_pvt::channel, dahdi_sig_pri_lib_handles(), LOG_WARNING, dahdi_pvt::manages_span_alarms, publish_channel_alarm(), publish_span_alarm(), report_alarms, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, dahdi_pvt::sig, sig_pri_is_alarm_ignored(), and dahdi_pvt::span.

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

◆ handle_clear_alarms()

static void handle_clear_alarms ( struct dahdi_pvt p)
static

Definition at line 3784 of file chan_dahdi.c.

3785{
3786#if defined(HAVE_PRI)
3788 return;
3789 }
3790#endif /* defined(HAVE_PRI) */
3791
3794 }
3797 }
3798}
static void publish_channel_alarm_clear(int channel)
Definition: chan_dahdi.c:3753
static void publish_span_alarm_clear(int span)
Definition: chan_dahdi.c:3771

References dahdi_pvt::channel, dahdi_sig_pri_lib_handles(), dahdi_pvt::manages_span_alarms, publish_channel_alarm_clear(), publish_span_alarm_clear(), report_alarms, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, dahdi_pvt::sig, sig_pri_is_alarm_ignored(), and dahdi_pvt::span.

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

◆ handle_dahdi_show_cadences()

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

Definition at line 16261 of file chan_dahdi.c.

16262{
16263 int i, j;
16264 switch (cmd) {
16265 case CLI_INIT:
16266 e->command = "dahdi show cadences";
16267 e->usage =
16268 "Usage: dahdi show cadences\n"
16269 " Shows all cadences currently defined\n";
16270 return NULL;
16271 case CLI_GENERATE:
16272 return NULL;
16273 }
16274 for (i = 0; i < num_cadence; i++) {
16275 char output[1024];
16276 char tmp[16], tmp2[64];
16277 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
16278 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
16279
16280 for (j = 0; j < 16; j++) {
16281 if (cadences[i].ringcadence[j] == 0)
16282 break;
16283 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
16284 if (cidrings[i] * 2 - 1 == j)
16285 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
16286 else
16287 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
16288 if (j != 0)
16289 strncat(output, ",", sizeof(output) - strlen(output) - 1);
16290 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
16291 }
16292 ast_cli(a->fd,"%s\n",output);
16293 }
16294 return CLI_SUCCESS;
16295}
static int cidrings[NUM_CADENCE_MAX]
cidrings says in which pause to transmit the cid information, where the first pause is 1,...
Definition: chan_dahdi.c:701
static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
Definition: chan_dahdi.c:690
static int num_cadence
Definition: chan_dahdi.c:685
#define COLOR_MAGENTA
Definition: term.h:60
#define COLOR_BLACK
Definition: term.h:50
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:235
#define COLOR_GREEN
Definition: term.h:54

References a, ast_cli(), cadences, cidrings, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, ast_cli_entry::command, NULL, num_cadence, term_color(), tmp(), and ast_cli_entry::usage.

◆ handle_init_event()

static struct dahdi_pvt * handle_init_event ( struct dahdi_pvt i,
int  event 
)
static

Definition at line 11583 of file chan_dahdi.c.

11584{
11585 int res;
11586 pthread_t threadid;
11587 struct ast_channel *chan;
11588 ast_callid callid = 0;
11589 int callid_created;
11590
11591 /* Handle an event on a given channel for the monitor thread. */
11592
11593 switch (event) {
11594 case DAHDI_EVENT_NONE:
11595 case DAHDI_EVENT_BITSCHANGED:
11596 break;
11597 case DAHDI_EVENT_WINKFLASH:
11598 case DAHDI_EVENT_RINGOFFHOOK:
11599 if (i->inalarm) break;
11600 if (i->radio) break;
11601 /* Got a ring/answer. What kind of channel are we? */
11602 switch (i->sig) {
11603 case SIG_FXOLS:
11604 case SIG_FXOGS:
11605 case SIG_FXOKS:
11606 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11607 if (res && (errno == EBUSY)) {
11608 break;
11609 }
11610
11611 callid_created = ast_callid_threadstorage_auto(&callid);
11612
11613 /* Cancel VMWI spill */
11614 ast_free(i->cidspill);
11615 i->cidspill = NULL;
11617
11618 if (i->immediate) {
11619 dahdi_ec_enable(i);
11620 /* The channel is immediately up. Start right away */
11621 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11622 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL, NULL, callid);
11623 if (!chan) {
11624 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11625 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11626 if (res < 0)
11627 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11628 }
11629 } else {
11630 /* Check for callerid, digits, etc */
11631 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL, NULL, callid);
11632 if (chan) {
11633 if (has_voicemail(i))
11634 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11635 else
11636 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11637 if (res < 0)
11638 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11639 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11640 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11641 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11642 if (res < 0)
11643 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11644 ast_hangup(chan);
11645 }
11646 } else
11647 ast_log(LOG_WARNING, "Unable to create channel\n");
11648 }
11649
11651 break;
11652 case SIG_FXSLS:
11653 case SIG_FXSGS:
11654 case SIG_FXSKS:
11655 i->ringt = i->ringt_base;
11656 /* Fall through */
11657 case SIG_EMWINK:
11658 case SIG_FEATD:
11659 case SIG_FEATDMF:
11660 case SIG_FEATDMF_TA:
11661 case SIG_E911:
11662 case SIG_FGC_CAMA:
11663 case SIG_FGC_CAMAMF:
11664 case SIG_FEATB:
11665 case SIG_EM:
11666 case SIG_EM_E1:
11667 case SIG_SFWINK:
11668 case SIG_SF_FEATD:
11669 case SIG_SF_FEATDMF:
11670 case SIG_SF_FEATB:
11671 case SIG_SF:
11672 /* Check for callerid, digits, etc */
11673 callid_created = ast_callid_threadstorage_auto(&callid);
11674 if (i->cid_start == CID_START_POLARITY_IN) {
11675 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11676 } else {
11677 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, callid);
11678 }
11679
11680 if (!chan) {
11681 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11682 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11683 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11684 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11685 if (res < 0) {
11686 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11687 }
11688 ast_hangup(chan);
11689 }
11690
11692 break;
11693 default:
11694 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11695 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11696 if (res < 0)
11697 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11698 return NULL;
11699 }
11700 break;
11701 case DAHDI_EVENT_NOALARM:
11702 switch (i->sig) {
11703#if defined(HAVE_PRI)
11705 ast_mutex_lock(&i->lock);
11708 break;
11709#endif /* defined(HAVE_PRI) */
11710#if defined(HAVE_SS7)
11711 case SIG_SS7:
11713 break;
11714#endif /* defined(HAVE_SS7) */
11715 default:
11716 i->inalarm = 0;
11717 break;
11718 }
11720 break;
11721 case DAHDI_EVENT_ALARM:
11722 switch (i->sig) {
11723#if defined(HAVE_PRI)
11725 ast_mutex_lock(&i->lock);
11728 break;
11729#endif /* defined(HAVE_PRI) */
11730#if defined(HAVE_SS7)
11731 case SIG_SS7:
11733 break;
11734#endif /* defined(HAVE_SS7) */
11735 default:
11736 i->inalarm = 1;
11737 break;
11738 }
11739 res = get_alarms(i);
11740 handle_alarms(i, res);
11741 /* fall thru intentionally */
11742 case DAHDI_EVENT_ONHOOK:
11743 if (i->radio)
11744 break;
11745 /* Back on hook. Hang up. */
11746 switch (i->sig) {
11747 case SIG_FXOLS:
11748 case SIG_FXOGS:
11749 case SIG_FEATD:
11750 case SIG_FEATDMF:
11751 case SIG_FEATDMF_TA:
11752 case SIG_E911:
11753 case SIG_FGC_CAMA:
11754 case SIG_FGC_CAMAMF:
11755 case SIG_FEATB:
11756 case SIG_EM:
11757 case SIG_EM_E1:
11758 case SIG_EMWINK:
11759 case SIG_SF_FEATD:
11760 case SIG_SF_FEATDMF:
11761 case SIG_SF_FEATB:
11762 case SIG_SF:
11763 case SIG_SFWINK:
11764 case SIG_FXSLS:
11765 case SIG_FXSGS:
11766 case SIG_FXSKS:
11767 case SIG_FXOKS:
11769 /* Diddle the battery for the zhone */
11770#ifdef ZHONE_HACK
11771 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11772 usleep(1);
11773#endif
11774 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11775 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11776 break;
11777 case SIG_SS7:
11780 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11781 break;
11782 default:
11783 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11784 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11785 return NULL;
11786 }
11787 break;
11788 case DAHDI_EVENT_POLARITY:
11789 switch (i->sig) {
11790 case SIG_FXSLS:
11791 case SIG_FXSKS:
11792 case SIG_FXSGS:
11793 /* We have already got a PR before the channel was
11794 created, but it wasn't handled. We need polarity
11795 to be REV for remote hangup detection to work.
11796 At least in Spain */
11797 callid_created = ast_callid_threadstorage_auto(&callid);
11802 ast_verb(2, "Starting post polarity "
11803 "CID detection on channel %d\n",
11804 i->channel);
11805 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11806 if (!chan) {
11807 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11808 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11809 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11810 ast_hangup(chan);
11811 }
11812 }
11814 break;
11815 default:
11816 ast_log(LOG_WARNING, "handle_init_event detected "
11817 "polarity reversal on non-FXO (SIG_FXS) "
11818 "interface %d\n", i->channel);
11819 }
11820 break;
11821 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11823 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11824 i->channel);
11825 return i;
11826 case DAHDI_EVENT_NEONMWI_ACTIVE:
11827 if (i->mwimonitor_neon) {
11828 notify_message(i->mailbox, 1);
11829 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11830 }
11831 break;
11832 case DAHDI_EVENT_NEONMWI_INACTIVE:
11833 if (i->mwimonitor_neon) {
11834 notify_message(i->mailbox, 0);
11835 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11836 }
11837 break;
11838 }
11839 return NULL;
11840}
static void notify_message(char *mailbox, int thereornot)
Send MWI state change.
Definition: chan_dahdi.c:3541
char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Voice mailbox location.
Definition: chan_dahdi.h:709
unsigned int mwimonitor_neon
TRUE if the FXO port monitors for neon type MWI indications from the other end.
Definition: chan_dahdi.h:418

References analog_ss_thread(), ast_callid_threadstorage_auto(), ast_callid_threadstorage_auto_clean(), 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, ast_channel::callid, dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::cidspill, dahdi_ec_disable(), dahdi_ec_enable(), 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(), NULL, 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().

◆ has_voicemail()

static int has_voicemail ( struct dahdi_pvt p)
static

Definition at line 5281 of file chan_dahdi.c.

5282{
5283 int new_msgs;
5284 RAII_VAR(struct stasis_message *, mwi_message, NULL, ao2_cleanup);
5285
5286 /* A manual MWI disposition has been requested, use that instead
5287 * if this is for sending the new MWI indication. */
5288 if (p->mwioverride_active) {
5289 /* We don't clear p->mwioverride_active automatically,
5290 * because otherwise do_monitor would just change it back to the way it was.
5291 * We need to keep the override active until explicitly disabled by the user,
5292 * so that we can keep returning the correct answer in subsequent calls to do_monitor. */
5293 ast_debug(6, "MWI manual override active on channel %d: pretending that it should be %s\n",
5294 p->channel, p->mwioverride_disposition ? "active" : "inactive");
5295 return p->mwioverride_disposition;
5296 }
5297
5299 if (mwi_message) {
5300 struct ast_mwi_state *mwi_state = stasis_message_data(mwi_message);
5301 new_msgs = mwi_state->new_msgs;
5302 } else {
5304 }
5305
5306 return new_msgs;
5307}
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX"....
Definition: main/app.c:582
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
struct stasis_cache * ast_mwi_state_cache(void)
Backend cache for ast_mwi_topic_cached().
Definition: mwi.c:94
struct stasis_message * stasis_cache_get(struct stasis_cache *cache, struct stasis_message_type *type, const char *id)
Retrieve an item from the cache for the ast_eid_default entity.
Definition: stasis_cache.c:686
The structure that contains MWI state.
Definition: mwi.h:455
int new_msgs
Definition: mwi.h:459

References ao2_cleanup, ast_app_has_voicemail(), ast_debug, ast_mwi_state_cache(), ast_mwi_state_type(), dahdi_pvt::channel, dahdi_pvt::mailbox, dahdi_pvt::mwioverride_active, dahdi_pvt::mwioverride_disposition, ast_mwi_state::new_msgs, NULL, RAII_VAR, stasis_cache_get(), and stasis_message_data().

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

◆ is_group_or_channel_match()

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

13428{
13429#if defined(HAVE_PRI)
13430 if (0 < span) {
13431 /* The channel must be on the specified PRI span. */
13432 if (!p->pri || p->pri->span != span) {
13433 return 0;
13434 }
13435 if (!groupmatch && channelmatch == -1) {
13436 /* Match any group since it only needs to be on the PRI span. */
13437 *groupmatched = 1;
13438 return 1;
13439 }
13440 }
13441#endif /* defined(HAVE_PRI) */
13442 /* check group matching */
13443 if (groupmatch) {
13444 if ((p->group & groupmatch) != groupmatch)
13445 /* Doesn't match the specified group, try the next one */
13446 return 0;
13447 *groupmatched = 1;
13448 }
13449 /* Check to see if we have a channel match */
13450 if (channelmatch != -1) {
13451 if (p->channel != channelmatch)
13452 /* Doesn't match the specified channel, try the next one */
13453 return 0;
13454 *channelmatched = 1;
13455 }
13456
13457 return 1;
13458}

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

Referenced by dahdi_cc_callback(), and dahdi_request().

◆ isourconf()

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

Definition at line 4743 of file chan_dahdi.c.

4744{
4745 /* If they're listening to our channel, they're ours */
4746 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
4747 return 1;
4748 /* If they're a talker on our (allocated) conference, they're ours */
4749 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
4750 return 1;
4751 return 0;
4752}

References c, dahdi_pvt::channel, and dahdi_pvt::confno.

Referenced by conf_del().

◆ isslavenative()

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

Definition at line 4773 of file chan_dahdi.c.

4774{
4775 int x;
4776 int useslavenative;
4777 struct dahdi_pvt *slave = NULL;
4778 /* Start out optimistic */
4779 useslavenative = 1;
4780 /* Update conference state in a stateless fashion */
4781 for (x = 0; x < 3; x++) {
4782 /* Any three-way calling makes slave native mode *definitely* out
4783 of the question */
4784 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
4785 useslavenative = 0;
4786 }
4787 /* If we don't have any 3-way calls, check to see if we have
4788 precisely one slave */
4789 if (useslavenative) {
4790 for (x = 0; x < MAX_SLAVES; x++) {
4791 if (p->slaves[x]) {
4792 if (slave) {
4793 /* Whoops already have a slave! No
4794 slave native and stop right away */
4795 slave = NULL;
4796 useslavenative = 0;
4797 break;
4798 } else {
4799 /* We have one slave so far */
4800 slave = p->slaves[x];
4801 }
4802 }
4803 }
4804 }
4805 /* If no slave, slave native definitely out */
4806 if (!slave)
4807 useslavenative = 0;
4808 else if (slave->law != p->law) {
4809 useslavenative = 0;
4810 slave = NULL;
4811 }
4812 if (out)
4813 *out = slave;
4814 return useslavenative;
4815}

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

Referenced by dahdi_conf_update(), and my_complete_conference_update().

◆ load_module()

static int load_module ( void  )
static

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 20267 of file chan_dahdi.c.

20268{
20269 int res;
20270#if defined(HAVE_PRI) || defined(HAVE_SS7)
20271 int y;
20272#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
20273
20274 if (STASIS_MESSAGE_TYPE_INIT(dahdichannel_type)) {
20276 }
20277
20280 }
20284
20288 }
20289
20290#ifdef HAVE_PRI
20291 memset(pris, 0, sizeof(pris));
20292 for (y = 0; y < NUM_SPANS; y++) {
20293 sig_pri_init_pri(&pris[y].pri);
20294 }
20295 pri_set_error(dahdi_pri_error);
20296 pri_set_message(dahdi_pri_message);
20297 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
20298#ifdef HAVE_PRI_PROG_W_CAUSE
20299 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
20300#endif
20301#if defined(HAVE_PRI_CCSS)
20302 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
20303 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
20306 }
20307#endif /* defined(HAVE_PRI_CCSS) */
20308 if (sig_pri_load(
20309#if defined(HAVE_PRI_CCSS)
20310 dahdi_pri_cc_type
20311#else
20312 NULL
20313#endif /* defined(HAVE_PRI_CCSS) */
20314 )) {
20317 }
20318#endif
20319#if defined(HAVE_SS7)
20320 memset(linksets, 0, sizeof(linksets));
20321 for (y = 0; y < NUM_SPANS; y++) {
20322 sig_ss7_init_linkset(&linksets[y].ss7);
20323 }
20324 ss7_set_error(dahdi_ss7_error);
20325 ss7_set_message(dahdi_ss7_message);
20326 ss7_set_hangup(sig_ss7_cb_hangup);
20327 ss7_set_notinservice(sig_ss7_cb_notinservice);
20328 ss7_set_call_null(sig_ss7_cb_call_null);
20329#endif /* defined(HAVE_SS7) */
20330 res = setup_dahdi(0);
20331 /* Make sure we can register our DAHDI channel type */
20332 if (res) {
20335 }
20337 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
20340 }
20341#ifdef HAVE_PRI
20342 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
20343#endif
20344#if defined(HAVE_SS7)
20345 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
20346#endif /* defined(HAVE_SS7) */
20347#ifdef HAVE_OPENR2
20348 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
20349 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
20350#endif
20351
20353
20355 memset(round_robin, 0, sizeof(round_robin));
20356 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
20358 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
20361 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
20362 ast_manager_register_xml("DAHDIShowStatus", 0, action_dahdishowstatus);
20364#if defined(HAVE_PRI)
20365 ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
20366 ast_manager_register_xml("PRIDebugSet", 0, action_pri_debug_set);
20367 ast_manager_register_xml("PRIDebugFileSet", EVENT_FLAG_SYSTEM, action_pri_debug_file_set);
20368 ast_manager_register_xml("PRIDebugFileUnset", 0, action_pri_debug_file_unset);
20369#endif /* defined(HAVE_PRI) */
20370
20372
20373 return res;
20374}
int dahdi_native_load(const struct ast_channel_tech *tech)
int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks)
Register a set of monitor callbacks with the core.
Definition: ccss.c:1162
int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
Register a set of agent callbacks with the core.
Definition: ccss.c:1217
static int __unload_module(void)
Definition: chan_dahdi.c:18096
static int action_transfer(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16816
static int action_dahdidndon(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16778
static int action_dahdishowchannels(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16894
static int action_dahdirestart(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:15967
static int action_dahdidndoff(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16797
static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16862
static int action_transferhangup(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16839
static int action_dahdishowstatus(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16982
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:539
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:191
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
int sig_pri_load(const char *cc_type_name)
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493

References __unload_module(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_dahdishowchannels(), action_dahdishowstatus(), action_transfer(), action_transferhangup(), ao2_ref, ARRAY_LEN, ast_cc_agent_register(), ast_cc_monitor_register(), ast_channel_register(), ast_cli_register_multiple, ast_cond_init, ast_custom_function_register, ast_format_alaw, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_slin, ast_format_ulaw, ast_log, ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, ast_register_application_xml, ast_channel_tech::capabilities, dahdi_cli, dahdi_native_load(), dahdi_tech, EVENT_FLAG_SYSTEM, LOG_ERROR, NULL, NUM_SPANS, polarity_function, round_robin, setup_dahdi(), sig_pri_init_pri(), sig_pri_load(), sig_ss7_cb_call_null(), sig_ss7_cb_hangup(), sig_ss7_cb_notinservice(), sig_ss7_init_linkset(), ss_thread_complete, and STASIS_MESSAGE_TYPE_INIT.

◆ mkintf()

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

< Current channel structure initializing

< TRUE if the channel interface already exists.

Definition at line 12481 of file chan_dahdi.c.

12482{
12483 /* Make a dahdi_pvt structure for this interface */
12484 struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12485 char fn[80];
12486 struct dahdi_bufferinfo bi;
12487
12488 int res;
12489#if defined(HAVE_PRI)
12490 int span = 0;
12491#endif /* defined(HAVE_PRI) */
12492 int here = 0;/*!< TRUE if the channel interface already exists. */
12493 int x;
12494 struct analog_pvt *analog_p = NULL;
12495 struct dahdi_params p;
12496#if defined(HAVE_PRI)
12497 struct dahdi_spaninfo si;
12498 struct sig_pri_chan *pri_chan = NULL;
12499#endif /* defined(HAVE_PRI) */
12500#if defined(HAVE_SS7)
12501 struct sig_ss7_chan *ss7_chan = NULL;
12502#endif /* defined(HAVE_SS7) */
12503
12504 /* Search channel interface list to see if it already exists. */
12505 for (tmp = iflist; tmp; tmp = tmp->next) {
12506 if (!tmp->destroy) {
12507 if (tmp->channel == channel) {
12508 /* The channel interface already exists. */
12509 here = 1;
12510 break;
12511 }
12512 if (tmp->channel > channel) {
12513 /* No way it can be in the sorted list. */
12514 tmp = NULL;
12515 break;
12516 }
12517 }
12518 }
12519
12520 if (!here && reloading != 1) {
12521 tmp = ast_calloc(1, sizeof(*tmp));
12522 if (!tmp) {
12523 return NULL;
12524 }
12525 tmp->cc_params = ast_cc_config_params_init();
12526 if (!tmp->cc_params) {
12527 ast_free(tmp);
12528 return NULL;
12529 }
12530 ast_mutex_init(&tmp->lock);
12531 ifcount++;
12532 for (x = 0; x < 3; x++)
12533 tmp->subs[x].dfd = -1;
12534 tmp->channel = channel;
12535 tmp->priindication_oob = conf->chan.priindication_oob;
12536 }
12537
12538 if (tmp) {
12539 int chan_sig = conf->chan.sig;
12540
12541 /* If there are variables in tmp before it is updated to match the new config, clear them */
12542 if (reloading && tmp->vars) {
12544 tmp->vars = NULL;
12545 }
12546
12547 if (!here) {
12548 /* Can only get here if this is a new channel interface being created. */
12549 if ((channel != CHAN_PSEUDO)) {
12550 int count = 0;
12551
12552 snprintf(fn, sizeof(fn), "%d", channel);
12553 /* Open non-blocking */
12554 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12555 /* Retry open on restarts, but don't keep retrying if the channel doesn't exist (e.g. not configured) */
12556 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000 && errno != ENXIO) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
12557 usleep(1);
12558 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12559 count++;
12560 }
12561 /* Allocate a DAHDI structure */
12562 if (tmp->subs[SUB_REAL].dfd < 0) {
12563 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);
12565 return NULL;
12566 }
12567 memset(&p, 0, sizeof(p));
12568 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12569 if (res < 0) {
12570 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12572 return NULL;
12573 }
12574 if (conf->is_sig_auto)
12575 chan_sig = sigtype_to_signalling(p.sigtype);
12576 if (p.sigtype != (chan_sig & 0x3ffff)) {
12577 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));
12579 return NULL;
12580 }
12581 tmp->law_default = p.curlaw;
12582 tmp->law = p.curlaw;
12583 tmp->span = p.spanno;
12584#if defined(HAVE_PRI)
12585 span = p.spanno - 1;
12586#endif /* defined(HAVE_PRI) */
12587 } else {
12588 chan_sig = 0;
12589 }
12590 tmp->sig = chan_sig;
12591 tmp->outsigmod = conf->chan.outsigmod;
12592
12593 if (dahdi_analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12594 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), tmp);
12595 if (!analog_p) {
12597 return NULL;
12598 }
12599 tmp->sig_pvt = analog_p;
12600 }
12601#if defined(HAVE_SS7)
12602 if (chan_sig == SIG_SS7) {
12603 struct dahdi_ss7 *ss7;
12604 int clear = 0;
12605
12606 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12607 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12609 return NULL;
12610 }
12611
12612 ss7 = ss7_resolve_linkset(cur_linkset);
12613 if (!ss7) {
12614 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12616 return NULL;
12617 }
12618 ss7->ss7.span = cur_linkset;
12619 if (cur_cicbeginswith < 0) {
12620 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12622 return NULL;
12623 }
12624 ss7_chan = sig_ss7_chan_new(tmp, &ss7->ss7);
12625 if (!ss7_chan) {
12627 return NULL;
12628 }
12629 tmp->sig_pvt = ss7_chan;
12630 tmp->ss7 = &ss7->ss7;
12631
12632 ss7_chan->channel = tmp->channel;
12633 ss7_chan->cic = cur_cicbeginswith++;
12634
12635 /* DB: Add CIC's DPC information */
12636 ss7_chan->dpc = cur_defaultdpc;
12637
12638 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12639
12640 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12641 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12642 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12643 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12644 ast_copy_string(ss7->ss7.networkroutedprefix, conf->ss7.ss7.networkroutedprefix, sizeof(ss7->ss7.networkroutedprefix));
12645
12646 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12647 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12648 }
12649#endif /* defined(HAVE_SS7) */
12650#ifdef HAVE_OPENR2
12651 if (chan_sig == SIG_MFCR2) {
12652 struct dahdi_mfcr2 *r2_link;
12653 struct r2link_entry *r2_le = dahdi_r2_get_link(conf);
12654 r2_link = &r2_le->mfcr2;
12655 if (!r2_link) {
12656 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12658 return NULL;
12659 }
12660 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12661 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12663 return NULL;
12664 }
12665 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12666 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12668 return NULL;
12669 }
12670 r2_link->pvts[r2_link->numchans++] = tmp;
12671 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12672 tmp->subs[SUB_REAL].dfd,
12673 NULL, NULL);
12674 if (!tmp->r2chan) {
12675 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12676 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12678 return NULL;
12679 }
12680 r2_link->live_chans++;
12681 tmp->mfcr2 = r2_link;
12682 if (conf->mfcr2.call_files) {
12683 openr2_chan_enable_call_files(tmp->r2chan);
12684 }
12685 openr2_chan_set_client_data(tmp->r2chan, tmp);
12686 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
12687 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12688 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12689 tmp->mfcr2_category = conf->mfcr2.category;
12690 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12691 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12692 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12693 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12694 tmp->mfcr2call = 0;
12695 tmp->mfcr2_dnis_index = 0;
12696 tmp->mfcr2_ani_index = 0;
12697 }
12698#endif
12699#ifdef HAVE_PRI
12700 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12701 int offset;
12702 int matchesdchan;
12703 int x,y;
12704 int myswitchtype = 0;
12705
12706 offset = 0;
12707 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12708 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12710 return NULL;
12711 }
12712 if (span >= NUM_SPANS) {
12713 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12715 return NULL;
12716 } else {
12717 si.spanno = 0;
12718 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12719 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12721 return NULL;
12722 }
12723 /* Store the logical span first based upon the real span */
12724 tmp->logicalspan = pris[span].prilogicalspan;
12725 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12726 if (span < 0) {
12727 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12729 return NULL;
12730 }
12731 myswitchtype = conf->pri.pri.switchtype;
12732 /* Make sure this isn't a d-channel */
12733 matchesdchan=0;
12734 for (x = 0; x < NUM_SPANS; x++) {
12735 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12736 if (pris[x].dchannels[y] == tmp->channel) {
12737 matchesdchan = 1;
12738 break;
12739 }
12740 }
12741 }
12742 if (!matchesdchan) {
12743 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12744 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12746 return NULL;
12747 }
12748 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12749 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12751 return NULL;
12752 }
12753 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12754 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));
12756 return NULL;
12757 }
12758 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12759 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12761 return NULL;
12762 }
12763 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12764 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12766 return NULL;
12767 }
12768 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12769 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12771 return NULL;
12772 }
12773 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12774 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12776 return NULL;
12777 }
12778 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12779 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12780 pris[span].pri.trunkgroup);
12782 return NULL;
12783 }
12784
12785 pri_chan = sig_pri_chan_new(tmp, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12786 if (!pri_chan) {
12788 return NULL;
12789 }
12790 tmp->sig_pvt = pri_chan;
12791 tmp->pri = &pris[span].pri;
12792
12793 tmp->priexclusive = conf->chan.priexclusive;
12794
12795 if (!tmp->pri->cc_params) {
12796 tmp->pri->cc_params = ast_cc_config_params_init();
12797 if (!tmp->pri->cc_params) {
12799 return NULL;
12800 }
12801 }
12802 ast_cc_copy_config_params(tmp->pri->cc_params,
12803 conf->chan.cc_params);
12804
12805 pris[span].pri.sig = chan_sig;
12806 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12807 pris[span].pri.switchtype = myswitchtype;
12808 pris[span].pri.nsf = conf->pri.pri.nsf;
12809 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12810 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12811 pris[span].pri.cpndialplan = conf->pri.pri.cpndialplan;
12812 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12813 pris[span].pri.minunused = conf->pri.pri.minunused;
12814 pris[span].pri.minidle = conf->pri.pri.minidle;
12815 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12816 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12817 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12818#if defined(HAVE_PRI_SERVICE_MESSAGES)
12819 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12820#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12821#ifdef HAVE_PRI_INBANDDISCONNECT
12822 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12823#endif
12824#if defined(HAVE_PRI_CALL_HOLD)
12825 pris[span].pri.hold_disconnect_transfer =
12826 conf->pri.pri.hold_disconnect_transfer;
12827#endif /* defined(HAVE_PRI_CALL_HOLD) */
12828#if defined(HAVE_PRI_CCSS)
12829 pris[span].pri.cc_ptmp_recall_mode =
12830 conf->pri.pri.cc_ptmp_recall_mode;
12831 pris[span].pri.cc_qsig_signaling_link_req =
12832 conf->pri.pri.cc_qsig_signaling_link_req;
12833 pris[span].pri.cc_qsig_signaling_link_rsp =
12834 conf->pri.pri.cc_qsig_signaling_link_rsp;
12835#endif /* defined(HAVE_PRI_CCSS) */
12836#if defined(HAVE_PRI_CALL_WAITING)
12837 pris[span].pri.max_call_waiting_calls =
12838 conf->pri.pri.max_call_waiting_calls;
12839 pris[span].pri.allow_call_waiting_calls =
12840 conf->pri.pri.allow_call_waiting_calls;
12841#endif /* defined(HAVE_PRI_CALL_WAITING) */
12842 pris[span].pri.transfer = conf->chan.transfer;
12843 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12844#if defined(HAVE_PRI_L2_PERSISTENCE)
12845 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12846#endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
12847 pris[span].pri.colp_send = conf->pri.pri.colp_send;
12848#if defined(HAVE_PRI_AOC_EVENTS)
12849 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12850 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12851#endif /* defined(HAVE_PRI_AOC_EVENTS) */
12852 if (chan_sig == SIG_BRI_PTMP) {
12853 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12854 } else {
12855 /* Option does not apply to this line type. */
12856 pris[span].pri.layer1_ignored = 0;
12857 }
12858 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12859 pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack;
12860 pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12861 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12862 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12863#if defined(HAVE_PRI_MWI)
12864 ast_copy_string(pris[span].pri.mwi_mailboxes,
12865 conf->pri.pri.mwi_mailboxes,
12866 sizeof(pris[span].pri.mwi_mailboxes));
12867 ast_copy_string(pris[span].pri.mwi_vm_boxes,
12868 conf->pri.pri.mwi_vm_boxes,
12869 sizeof(pris[span].pri.mwi_vm_boxes));
12870 ast_copy_string(pris[span].pri.mwi_vm_numbers,
12871 conf->pri.pri.mwi_vm_numbers,
12872 sizeof(pris[span].pri.mwi_vm_numbers));
12873#endif /* defined(HAVE_PRI_MWI) */
12874 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12875 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12876 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12877 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12878 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12879 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12880 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12881 pris[span].pri.moh_signaling = conf->pri.pri.moh_signaling;
12882 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12883#if defined(HAVE_PRI_DISPLAY_TEXT)
12884 pris[span].pri.display_flags_send = conf->pri.pri.display_flags_send;
12885 pris[span].pri.display_flags_receive = conf->pri.pri.display_flags_receive;
12886#endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
12887#if defined(HAVE_PRI_MCID)
12888 pris[span].pri.mcid_send = conf->pri.pri.mcid_send;
12889#endif /* defined(HAVE_PRI_MCID) */
12890 pris[span].pri.force_restart_unavailable_chans = conf->pri.pri.force_restart_unavailable_chans;
12891#if defined(HAVE_PRI_DATETIME_SEND)
12892 pris[span].pri.datetime_send = conf->pri.pri.datetime_send;
12893#endif /* defined(HAVE_PRI_DATETIME_SEND) */
12894
12895 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12896 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12897 }
12898
12899#if defined(HAVE_PRI_CALL_WAITING)
12900 /* Channel initial config parameters. */
12901 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12902 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12903 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12904 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12905 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12906 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12907 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12908 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12909 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12910 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12911#endif /* defined(HAVE_PRI_CALL_WAITING) */
12912 } else {
12913 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12915 return NULL;
12916 }
12917 }
12918 }
12919#endif
12920 } else {
12921 /* already exists in interface list */
12922 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));
12923 chan_sig = tmp->sig;
12924 if (tmp->subs[SUB_REAL].dfd > -1) {
12925 memset(&p, 0, sizeof(p));
12926 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12927 }
12928 }
12929 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12930 switch (chan_sig) {
12931 case SIG_FXSKS:
12932 case SIG_FXSLS:
12933 case SIG_EM:
12934 case SIG_EM_E1:
12935 case SIG_EMWINK:
12936 case SIG_FEATD:
12937 case SIG_FEATDMF:
12938 case SIG_FEATDMF_TA:
12939 case SIG_FEATB:
12940 case SIG_E911:
12941 case SIG_SF:
12942 case SIG_SFWINK:
12943 case SIG_FGC_CAMA:
12944 case SIG_FGC_CAMAMF:
12945 case SIG_SF_FEATD:
12946 case SIG_SF_FEATDMF:
12947 case SIG_SF_FEATB:
12948 p.starttime = 250;
12949 break;
12950 }
12951
12952 if (tmp->radio) {
12953 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12954 p.channo = channel;
12955 p.rxwinktime = 1;
12956 p.rxflashtime = 1;
12957 p.starttime = 1;
12958 p.debouncetime = 5;
12959 } else {
12960 p.channo = channel;
12961 /* Override timing settings based on config file */
12962 if (conf->timing.prewinktime >= 0)
12963 p.prewinktime = conf->timing.prewinktime;
12964 if (conf->timing.preflashtime >= 0)
12965 p.preflashtime = conf->timing.preflashtime;
12966 if (conf->timing.winktime >= 0)
12967 p.winktime = conf->timing.winktime;
12968 if (conf->timing.flashtime >= 0)
12969 p.flashtime = conf->timing.flashtime;
12970 if (conf->timing.starttime >= 0)
12971 p.starttime = conf->timing.starttime;
12972 if (conf->timing.rxwinktime >= 0)
12973 p.rxwinktime = conf->timing.rxwinktime;
12974 if (conf->timing.rxflashtime >= 0)
12975 p.rxflashtime = conf->timing.rxflashtime;
12976 if (conf->timing.debouncetime >= 0)
12977 p.debouncetime = conf->timing.debouncetime;
12978 }
12979
12980 /* don't set parms on a pseudo-channel */
12981 if (tmp->subs[SUB_REAL].dfd >= 0)
12982 {
12983 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12984 if (res < 0) {
12985 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12987 return NULL;
12988 }
12989 }
12990#if 1
12991 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12992 memset(&bi, 0, sizeof(bi));
12993 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12994 if (!res) {
12995 bi.txbufpolicy = conf->chan.buf_policy;
12996 bi.rxbufpolicy = conf->chan.buf_policy;
12997 bi.numbufs = conf->chan.buf_no;
12998 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12999 if (res < 0) {
13000 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
13001 }
13002 } else {
13003 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
13004 }
13005 tmp->buf_policy = conf->chan.buf_policy;
13006 tmp->buf_no = conf->chan.buf_no;
13007 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
13008 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
13009 tmp->faxbuf_no = conf->chan.faxbuf_no;
13010 /* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting
13011 * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
13012 * The reason the ioctl call above failed should to be determined before worrying about the
13013 * faxbuffer-related ioctl calls */
13014 tmp->bufsize = bi.bufsize;
13015 }
13016#endif
13017 tmp->immediate = conf->chan.immediate;
13018 tmp->immediatering = conf->chan.immediatering;
13019 tmp->transfertobusy = conf->chan.transfertobusy;
13020 tmp->dialmode = conf->chan.dialmode;
13021 if (chan_sig & __DAHDI_SIG_FXS) {
13022 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
13023 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
13024 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
13025 }
13026 tmp->ringt_base = ringt_base;
13027 tmp->firstradio = 0;
13028 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
13029 tmp->permcallwaiting = conf->chan.callwaiting;
13030 else
13031 tmp->permcallwaiting = 0;
13032 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
13033 tmp->destroy = 0;
13034 tmp->drings = conf->chan.drings;
13035
13036 /* 10 is a nice default. */
13037 if (tmp->drings.ringnum[0].range == 0)
13038 tmp->drings.ringnum[0].range = 10;
13039 if (tmp->drings.ringnum[1].range == 0)
13040 tmp->drings.ringnum[1].range = 10;
13041 if (tmp->drings.ringnum[2].range == 0)
13042 tmp->drings.ringnum[2].range = 10;
13043
13044 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
13045 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
13046 tmp->threewaycalling = conf->chan.threewaycalling;
13047 tmp->threewaysilenthold = conf->chan.threewaysilenthold;
13048 tmp->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Not used in chan_dahdi.c, just analog pvt, but must exist on the DAHDI pvt anyways */
13049 tmp->adsi = conf->chan.adsi;
13050 tmp->use_smdi = conf->chan.use_smdi;
13051 tmp->permhidecallerid = conf->chan.hidecallerid;
13052 tmp->hidecalleridname = conf->chan.hidecalleridname;
13053 tmp->callreturn = conf->chan.callreturn;
13054 tmp->echocancel = conf->chan.echocancel;
13055 tmp->echotraining = conf->chan.echotraining;
13056 tmp->pulse = conf->chan.pulse;
13057 if (tmp->echocancel.head.tap_length) {
13058 tmp->echocanbridged = conf->chan.echocanbridged;
13059 } else {
13060 if (conf->chan.echocanbridged)
13061 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
13062 tmp->echocanbridged = 0;
13063 }
13064 tmp->busydetect = conf->chan.busydetect;
13065 tmp->busycount = conf->chan.busycount;
13066 tmp->busy_cadence = conf->chan.busy_cadence;
13067 tmp->callprogress = conf->chan.callprogress;
13068 tmp->waitfordialtone = conf->chan.waitfordialtone;
13069 tmp->dialtone_detect = conf->chan.dialtone_detect;
13070 tmp->faxdetect_timeout = conf->chan.faxdetect_timeout;
13071 tmp->firstdigit_timeout = conf->chan.firstdigit_timeout;
13072 tmp->interdigit_timeout = conf->chan.interdigit_timeout;
13073 tmp->matchdigit_timeout = conf->chan.matchdigit_timeout;
13074 tmp->cancallforward = conf->chan.cancallforward;
13075 tmp->dtmfrelax = conf->chan.dtmfrelax;
13076 tmp->callwaiting = tmp->permcallwaiting;
13077 tmp->hidecallerid = tmp->permhidecallerid;
13078 tmp->channel = channel;
13079 tmp->stripmsd = conf->chan.stripmsd;
13080 tmp->use_callerid = conf->chan.use_callerid;
13081 tmp->cid_signalling = conf->chan.cid_signalling;
13082 tmp->cid_start = conf->chan.cid_start;
13083 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
13084 tmp->restrictcid = conf->chan.restrictcid;
13085 tmp->use_callingpres = conf->chan.use_callingpres;
13086 if (tmp->usedistinctiveringdetection) {
13087 if (!tmp->use_callerid) {
13088 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
13089 tmp->use_callerid = 1;
13090 }
13091 }
13092
13093 if (tmp->cid_signalling == CID_SIG_SMDI) {
13094 if (!tmp->use_smdi) {
13095 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
13096 tmp->use_smdi = 1;
13097 }
13098 }
13099 if (tmp->use_smdi) {
13100 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
13101 if (!(tmp->smdi_iface)) {
13102 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
13103 tmp->use_smdi = 0;
13104 }
13105 }
13106
13107 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
13108 tmp->amaflags = conf->chan.amaflags;
13109 if (!here) {
13110 tmp->confno = -1;
13111 tmp->propconfno = -1;
13112 }
13113 tmp->canpark = conf->chan.canpark;
13114 tmp->transfer = conf->chan.transfer;
13115 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
13116 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
13117 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
13118 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
13119 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
13120 ast_copy_string(tmp->description, conf->chan.description, sizeof(tmp->description));
13121 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
13122 tmp->cid_ton = 0;
13123 if (dahdi_analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
13124 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
13125 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
13126 } else {
13127 tmp->cid_num[0] = '\0';
13128 tmp->cid_name[0] = '\0';
13129 }
13130#if defined(HAVE_PRI)
13131 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
13132 tmp->cid_tag[0] = '\0';
13133 } else
13134#endif /* defined(HAVE_PRI) */
13135 {
13136 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
13137 }
13138 tmp->cid_subaddr[0] = '\0';
13139 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
13140 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
13141 /* This module does not handle MWI in an event-based manner. However, it
13142 * subscribes to MWI for each mailbox that is configured so that the core
13143 * knows that we care about it. Then, chan_dahdi will get the MWI from the
13144 * event cache instead of checking the mailbox directly. */
13145 tmp->mwi_event_sub = ast_mwi_subscribe_pool(tmp->mailbox, stasis_subscription_cb_noop, NULL);
13146 }
13147#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13148 tmp->mwisend_setting = conf->chan.mwisend_setting;
13149 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
13150 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
13151#endif
13152
13153 tmp->group = conf->chan.group;
13154 tmp->callgroup = conf->chan.callgroup;
13155 tmp->pickupgroup= conf->chan.pickupgroup;
13156 ast_unref_namedgroups(tmp->named_callgroups);
13157 tmp->named_callgroups = ast_ref_namedgroups(conf->chan.named_callgroups);
13158 ast_unref_namedgroups(tmp->named_pickupgroups);
13159 tmp->named_pickupgroups = ast_ref_namedgroups(conf->chan.named_pickupgroups);
13160 if (conf->chan.vars) {
13161 struct ast_variable *v, *tmpvar;
13162 for (v = conf->chan.vars ; v ; v = v->next) {
13163 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
13164 if (ast_variable_list_replace(&tmp->vars, tmpvar)) {
13165 tmpvar->next = tmp->vars;
13166 tmp->vars = tmpvar;
13167 }
13168 }
13169 }
13170 }
13171 tmp->hwrxgain_enabled = conf->chan.hwrxgain_enabled;
13172 tmp->hwtxgain_enabled = conf->chan.hwtxgain_enabled;
13173 tmp->hwrxgain = conf->chan.hwrxgain;
13174 tmp->hwtxgain = conf->chan.hwtxgain;
13175 tmp->cid_rxgain = conf->chan.cid_rxgain;
13176 tmp->rxgain = conf->chan.rxgain;
13177 tmp->txgain = conf->chan.txgain;
13178 tmp->txdrc = conf->chan.txdrc;
13179 tmp->rxdrc = conf->chan.rxdrc;
13180 tmp->tonezone = conf->chan.tonezone;
13181 if (tmp->subs[SUB_REAL].dfd > -1) {
13182 if (tmp->hwrxgain_enabled) {
13183 tmp->hwrxgain_enabled = !set_hwgain(tmp->subs[SUB_REAL].dfd, tmp->hwrxgain, 0);
13184 }
13185 if (tmp->hwtxgain_enabled) {
13186 tmp->hwtxgain_enabled = !set_hwgain(tmp->subs[SUB_REAL].dfd, tmp->hwtxgain, 1);
13187 }
13188 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13189 if (tmp->dsp)
13190 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13192 if (!here) {
13193 switch (chan_sig) {
13195 case SIG_SS7:
13196 case SIG_MFCR2:
13197 break;
13198 default:
13199 /* Hang it up to be sure it's good */
13200 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13201 break;
13202 }
13203 }
13204 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13205 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13206 /* the dchannel is down so put the channel in alarm */
13207 switch (tmp->sig) {
13208#ifdef HAVE_PRI
13210 sig_pri_set_alarm(tmp->sig_pvt, 1);
13211 break;
13212#endif
13213#if defined(HAVE_SS7)
13214 case SIG_SS7:
13215 sig_ss7_set_alarm(tmp->sig_pvt, 1);
13216 break;
13217#endif /* defined(HAVE_SS7) */
13218 default:
13219 /* The only sig submodule left should be sig_analog. */
13220 analog_p = tmp->sig_pvt;
13221 if (analog_p) {
13222 analog_p->inalarm = 1;
13223 }
13224 tmp->inalarm = 1;
13225 break;
13226 }
13227 handle_alarms(tmp, res);
13228 }
13229 }
13230
13231 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13232 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13233 tmp->ani_info_digits = conf->chan.ani_info_digits;
13234 tmp->ani_wink_time = conf->chan.ani_wink_time;
13235 tmp->ani_timeout = conf->chan.ani_timeout;
13236 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13237 tmp->reoriginate = conf->chan.reoriginate;
13238 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13239 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13240
13241 if (!here) {
13242 tmp->locallyblocked = 0;
13243 tmp->remotelyblocked = 0;
13244 switch (tmp->sig) {
13245#if defined(HAVE_PRI)
13247 tmp->inservice = 1;/* Inservice until actually implemented. */
13248#if defined(HAVE_PRI_SERVICE_MESSAGES)
13249 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13250 if (chan_sig == SIG_PRI) {
13251 char db_chan_name[20];
13252 char db_answer[5];
13253
13254 /*
13255 * Initialize the active out-of-service status
13256 * and delete any record if the feature is not enabled.
13257 */
13258 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13259 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13260 unsigned *why;
13261
13262 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13263 if (tmp->pri->enable_service_message_support) {
13264 char state;
13265
13266 sscanf(db_answer, "%1c:%30u", &state, why);
13267
13268 /* Ensure that only the implemented bits could be set.*/
13269 *why &= (SRVST_NEAREND | SRVST_FAREND);
13270 }
13271 if (!*why) {
13272 ast_db_del(db_chan_name, SRVST_DBKEY);
13273 }
13274 }
13275 }
13276#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13277 break;
13278#endif /* defined(HAVE_PRI) */
13279#if defined(HAVE_SS7)
13280 case SIG_SS7:
13281 tmp->inservice = 0;
13282 if (tmp->ss7->flags & LINKSET_FLAG_INITIALHWBLO) {
13283 tmp->remotelyblocked |= SS7_BLOCKED_HARDWARE;
13284 }
13285 break;
13286#endif /* defined(HAVE_SS7) */
13287 default:
13288 /* We default to in service on protocols that don't have a reset */
13289 tmp->inservice = 1;
13290 break;
13291 }
13292 }
13293
13294 switch (tmp->sig) {
13295#if defined(HAVE_PRI)
13297 if (pri_chan) {
13298 pri_chan->channel = tmp->channel;
13299 pri_chan->hidecallerid = tmp->hidecallerid;
13300 pri_chan->hidecalleridname = tmp->hidecalleridname;
13301 pri_chan->immediate = tmp->immediate;
13302 pri_chan->inalarm = tmp->inalarm;
13303 pri_chan->priexclusive = tmp->priexclusive;
13304 pri_chan->priindication_oob = tmp->priindication_oob;
13305 pri_chan->use_callerid = tmp->use_callerid;
13306 pri_chan->use_callingpres = tmp->use_callingpres;
13307 ast_copy_string(pri_chan->context, tmp->context,
13308 sizeof(pri_chan->context));
13309 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13310 sizeof(pri_chan->mohinterpret));
13311 pri_chan->stripmsd = tmp->stripmsd;
13312 }
13313 break;
13314#endif /* defined(HAVE_PRI) */
13315#if defined(HAVE_SS7)
13316 case SIG_SS7:
13317 if (ss7_chan) {
13318 ss7_chan->inalarm = tmp->inalarm;
13319 ss7_chan->inservice = tmp->inservice;
13320
13321 ss7_chan->stripmsd = tmp->stripmsd;
13322 ss7_chan->hidecallerid = tmp->hidecallerid;
13323 ss7_chan->use_callerid = tmp->use_callerid;
13324 ss7_chan->use_callingpres = tmp->use_callingpres;
13325 ss7_chan->immediate = tmp->immediate;
13326 ss7_chan->locallyblocked = tmp->locallyblocked;
13327 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13328 ast_copy_string(ss7_chan->context, tmp->context,
13329 sizeof(ss7_chan->context));
13330 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13331 sizeof(ss7_chan->mohinterpret));
13332 }
13333 break;
13334#endif /* defined(HAVE_SS7) */
13335 default:
13336 /* The only sig submodule left should be sig_analog. */
13337 analog_p = tmp->sig_pvt;
13338 if (analog_p) {
13339 analog_p->channel = tmp->channel;
13340 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13341 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13342 analog_p->ani_info_digits = conf->chan.ani_info_digits;
13343 analog_p->ani_timeout = conf->chan.ani_timeout;
13344 analog_p->ani_wink_time = conf->chan.ani_wink_time;
13345 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13346 analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13347 analog_p->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Only actually used in analog pvt, not DAHDI pvt */
13348 analog_p->callreturn = conf->chan.callreturn;
13349 analog_p->cancallforward = conf->chan.cancallforward;
13350 analog_p->canpark = conf->chan.canpark;
13351 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13352 analog_p->immediate = conf->chan.immediate;
13353 analog_p->immediatering = conf->chan.immediatering;
13354 analog_p->permhidecallerid = conf->chan.hidecallerid; /* hidecallerid is the config setting, not permhidecallerid (~permcallwaiting above) */
13355 /* It's not necessary to set analog_p->hidecallerid here, sig_analog will set hidecallerid=permhidecaller before each call */
13356 analog_p->pulse = conf->chan.pulse;
13357 analog_p->threewaycalling = conf->chan.threewaycalling;
13358 analog_p->transfer = conf->chan.transfer;
13359 analog_p->transfertobusy = conf->chan.transfertobusy;
13360 analog_p->dialmode = conf->chan.dialmode;
13361 analog_p->use_callerid = tmp->use_callerid;
13362 analog_p->usedistinctiveringdetection = tmp->usedistinctiveringdetection;
13363 analog_p->use_smdi = tmp->use_smdi;
13364 analog_p->smdi_iface = tmp->smdi_iface;
13365 analog_p->outsigmod = ANALOG_SIG_NONE;
13366 analog_p->echotraining = conf->chan.echotraining;
13367 analog_p->cid_signalling = conf->chan.cid_signalling;
13368 analog_p->stripmsd = conf->chan.stripmsd;
13369 switch (conf->chan.cid_start) {
13370 case CID_START_POLARITY:
13372 break;
13375 break;
13378 break;
13379 default:
13380 analog_p->cid_start = ANALOG_CID_START_RING;
13381 break;
13382 }
13383 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13384 analog_p->ringt = conf->chan.ringt;
13385 analog_p->ringt_base = ringt_base;
13386 analog_p->onhooktime = time(NULL);
13387 if (chan_sig & __DAHDI_SIG_FXO) {
13388 memset(&p, 0, sizeof(p));
13389 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13390 if (!res) {
13391 analog_p->fxsoffhookstate = p.rxisoffhook;
13392 }
13393#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13394 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13395#endif
13396 }
13397 analog_p->msgstate = -1;
13398
13399 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13400 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13401 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13402
13403 analog_config_complete(analog_p);
13404 }
13405 break;
13406 }
13407#if defined(HAVE_PRI)
13408 if (tmp->channel == CHAN_PSEUDO) {
13409 /*
13410 * Save off pseudo channel buffer policy values for dynamic creation of
13411 * no B channel interfaces.
13412 */
13413 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13414 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13415 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13416 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13417 }
13418#endif /* defined(HAVE_PRI) */
13419 }
13420 if (tmp && !here) {
13421 /* Add the new channel interface to the sorted channel interface list. */
13423 }
13424 return tmp;
13425}
static char * dahdi_sig2str(int sig)
Definition: chan_dahdi.c:4639
static int sigtype_to_signalling(int sigtype)
Definition: chan_dahdi.c:12462
static int ringt_base
Configured ring timeout base.
Definition: chan_dahdi.c:811
static enum analog_sigtype dahdisig_to_analogsig(int sig)
Definition: chan_dahdi.c:1182
static int usedistinctiveringdetection
Definition: chan_dahdi.c:728
struct ast_namedgroups * ast_ref_namedgroups(struct ast_namedgroups *groups)
Definition: channel.c:7738
#define ast_variable_new(name, value, filename)
int ast_variable_list_replace(struct ast_variable **head, struct ast_variable *replacement)
Replace a variable in the given list with a new value.
Definition: main/config.c:667
struct ast_mwi_subscriber * ast_mwi_subscribe_pool(const char *mailbox, stasis_subscription_cb callback, void *data)
Add an MWI state subscriber, and stasis subscription to the mailbox.
Definition: mwi.c:235
int analog_config_complete(struct analog_pvt *p)
Definition: sig_analog.c:4109
struct analog_pvt * analog_new(enum analog_sigtype signallingtype, void *private_data)
Definition: sig_analog.c:4076
@ ANALOG_SIG_NONE
Definition: sig_analog.h:46
@ ANALOG_CID_START_RING
Definition: sig_analog.h:129
@ ANALOG_CID_START_DTMF_NOALERT
Definition: sig_analog.h:130
@ ANALOG_CID_START_POLARITY
Definition: sig_analog.h:127
@ ANALOG_CID_START_POLARITY_IN
Definition: sig_analog.h:128
struct sig_pri_chan * sig_pri_chan_new(void *pvt_data, struct sig_pri_span *pri, int logicalspan, int channo, int trunkgroup)
void sig_pri_set_alarm(struct sig_pri_chan *p, int in_alarm)
struct sig_ss7_chan * sig_ss7_chan_new(void *pvt_data, struct sig_ss7_linkset *ss7)
#define LINKSET_FLAG_INITIALHWBLO
Definition: sig_ss7.h:69
#define SS7_BLOCKED_HARDWARE
Definition: sig_ss7.h:75
struct ast_smdi_interface * ast_smdi_interface_find(const char *iface_name)
Find an SMDI interface with the specified name.
Definition: res_smdi.c:563
void stasis_subscription_cb_noop(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Stasis subscription callback function that does nothing.
Definition: stasis.c:809
unsigned int immediate
Definition: sig_analog.h:298
unsigned int immediatering
Definition: sig_analog.h:299
unsigned int permcallwaiting
Definition: sig_analog.h:300
unsigned int canpark
Definition: sig_analog.h:295
unsigned int dahditrcallerid
Definition: sig_analog.h:296
int polarityonanswerdelay
Definition: sig_analog.h:324
char cid_num[AST_MAX_EXTENSION]
Definition: sig_analog.h:328
unsigned int permhidecallerid
Definition: sig_analog.h:301
unsigned int callwaitingcallerid
Definition: sig_analog.h:309
unsigned int ani_wink_time
Definition: sig_analog.h:289
enum analog_sigtype outsigmod
Definition: sig_analog.h:320
unsigned int usedistinctiveringdetection
Definition: sig_analog.h:308
unsigned int answeronpolarityswitch
Definition: sig_analog.h:291
unsigned int threewaycalling
Definition: sig_analog.h:303
unsigned int pulse
Definition: sig_analog.h:302
int echotraining
Definition: sig_analog.h:322
unsigned int hanguponpolarityswitch
Definition: sig_analog.h:297
enum analog_cid_start cid_start
Definition: sig_analog.h:326
unsigned int callreturn
Definition: sig_analog.h:293
unsigned int use_smdi
TRUE if SMDI (Simplified Message Desk Interface) is enabled.
Definition: sig_analog.h:313
unsigned int ani_timeout
Definition: sig_analog.h:288
int ringt_base
Definition: sig_analog.h:376
unsigned int ani_info_digits
Definition: sig_analog.h:287
unsigned int cancallforward
Definition: sig_analog.h:294
int cid_signalling
Definition: sig_analog.h:323
unsigned int transfer
Definition: sig_analog.h:305
unsigned int transfertobusy
Definition: sig_analog.h:306
unsigned int inalarm
Definition: sig_analog.h:341
char cid_name[AST_MAX_EXTENSION]
Definition: sig_analog.h:329
int stripmsd
Definition: sig_analog.h:325
unsigned int calledsubscriberheld
Definition: sig_analog.h:292
char mohsuggest[MAX_MUSICCLASS]
Definition: sig_analog.h:327
unsigned int use_callerid
Definition: sig_analog.h:307
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
Definition: sig_analog.h:315
unsigned int immediate
Definition: sig_pri.h:282
unsigned int use_callingpres
Definition: sig_pri.h:286
unsigned int priexclusive
Definition: sig_pri.h:283
unsigned int hidecallerid
Definition: sig_pri.h:280
unsigned int priindication_oob
Definition: sig_pri.h:284
unsigned int hidecalleridname
Definition: sig_pri.h:281
char context[AST_MAX_CONTEXT]
Definition: sig_pri.h:287
unsigned int inalarm
Definition: sig_pri.h:324
int stripmsd
Definition: sig_pri.h:289
unsigned int use_callerid
Definition: sig_pri.h:285
char mohinterpret[MAX_MUSICCLASS]
Definition: sig_pri.h:288
unsigned int immediate
Definition: sig_ss7.h:221
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: sig_ss7.h:228
unsigned int dpc
Definition: sig_ss7.h:202
unsigned int use_callingpres
TRUE if we will use the calling presentation setting from the Asterisk channel for outgoing calls.
Definition: sig_ss7.h:220
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked.
Definition: sig_ss7.h:235
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
Definition: sig_ss7.h:213
char context[AST_MAX_CONTEXT]
Definition: sig_ss7.h:237
unsigned int inalarm
TRUE if channel is associated with a link that is down.
Definition: sig_ss7.h:288
unsigned int inservice
TRUE if channel is in service.
Definition: sig_ss7.h:290
int channel
Definition: sig_ss7.h:200
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
Definition: sig_ss7.h:209
unsigned int use_callerid
TRUE if caller ID is used on this channel.
Definition: sig_ss7.h:215
char mohinterpret[MAX_MUSICCLASS]
Definition: sig_ss7.h:238

References ANALOG_CID_START_DTMF_NOALERT, ANALOG_CID_START_POLARITY, ANALOG_CID_START_POLARITY_IN, ANALOG_CID_START_RING, analog_config_complete(), analog_new(), ANALOG_SIG_NONE, analog_pvt::ani_info_digits, analog_pvt::ani_timeout, analog_pvt::ani_wink_time, analog_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_dsp_set_digitmode(), ast_free, ast_log, ast_mutex_init, ast_mwi_subscribe_pool(), ast_ref_namedgroups(), ast_smdi_interface_find(), ast_strlen_zero(), ast_unref_namedgroups(), ast_variable_list_replace(), ast_variable_new, ast_variables_destroy(), analog_pvt::calledsubscriberheld, analog_pvt::callreturn, analog_pvt::callwaitingcallerid, analog_pvt::cancallforward, analog_pvt::canpark, CHAN_PSEUDO, analog_pvt::channel, sig_pri_chan::channel, sig_ss7_chan::channel, sig_ss7_chan::cic, analog_pvt::cid_name, analog_pvt::cid_num, CID_SIG_SMDI, analog_pvt::cid_signalling, analog_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, CID_START_POLARITY_IN, sig_pri_chan::context, sig_ss7_chan::context, dahdi_analog_lib_handles(), dahdi_conf_update(), dahdi_iflist_insert(), dahdi_open(), dahdi_set_hook(), dahdi_sig2str(), dahdi_sig_pri_lib_handles(), dahdisig_to_analogsig(), analog_pvt::dahditrcallerid, destroy_dahdi_pvt(), analog_pvt::dialmode, sig_pri_span::dialplan, sig_ss7_chan::dpc, DSP_DIGITMODE_DTMF, analog_pvt::echotraining, errno, ast_variable::file, analog_pvt::fxsoffhookstate, get_alarms(), handle_alarms(), analog_pvt::hanguponpolarityswitch, sig_pri_chan::hidecallerid, sig_ss7_chan::hidecallerid, sig_pri_chan::hidecalleridname, sig_pri_span::idledial, sig_pri_span::idleext, ifcount, iflist, analog_pvt::immediate, sig_pri_chan::immediate, sig_ss7_chan::immediate, analog_pvt::immediatering, analog_pvt::inalarm, sig_pri_chan::inalarm, sig_ss7_chan::inalarm, sig_ss7_chan::inservice, LINKSET_FLAG_INITIALHWBLO, sig_ss7_chan::locallyblocked, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sig_pri_span::minidle, sig_pri_span::minunused, sig_pri_chan::mohinterpret, sig_ss7_chan::mohinterpret, analog_pvt::mohsuggest, analog_pvt::msgstate, ast_variable::name, ast_variable::next, sig_pri_span::nodetype, NULL, NUM_SPANS, sig_pri_span::numchans, analog_pvt::onhooktime, analog_pvt::outsigmod, analog_pvt::permcallwaiting, analog_pvt::permhidecallerid, analog_pvt::polarityonanswerdelay, sig_pri_chan::priexclusive, sig_pri_chan::priindication_oob, analog_pvt::pulse, sig_pri_span::pvts, sig_ss7_chan::remotelyblocked, analog_pvt::ringt, ringt_base, analog_pvt::ringt_base, set_actual_gain(), set_hwgain(), sig2str, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, sig_pri_chan_new(), SIG_PRI_LIB_HANDLE_CASES, SIG_PRI_NUM_DCHANS, sig_pri_set_alarm(), 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, SS7_BLOCKED_HARDWARE, stasis_subscription_cb_noop(), state, analog_pvt::stripmsd, sig_pri_chan::stripmsd, sig_ss7_chan::stripmsd, SUB_REAL, sig_pri_span::switchtype, analog_pvt::threewaycalling, tmp(), analog_pvt::transfer, analog_pvt::transfertobusy, sig_pri_span::trunkgroup, analog_pvt::use_callerid, sig_pri_chan::use_callerid, sig_ss7_chan::use_callerid, sig_pri_chan::use_callingpres, sig_ss7_chan::use_callingpres, analog_pvt::use_smdi, usedistinctiveringdetection, analog_pvt::usedistinctiveringdetection, and ast_variable::value.

Referenced by build_channels(), and process_dahdi().

◆ monitor_pfds_clean()

static void monitor_pfds_clean ( void *  arg)
static

Definition at line 11842 of file chan_dahdi.c.

11842 {
11843 struct pollfd **pfds = arg;
11844 ast_free(*pfds);
11845}

References ast_free.

Referenced by do_monitor().

◆ mwi_send_init()

static int mwi_send_init ( struct dahdi_pvt pvt)
static

Definition at line 11248 of file chan_dahdi.c.

11249{
11250 int x;
11251
11252#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11253 /* Determine how this spill is to be sent */
11254 if (pvt->mwisend_rpas) {
11256 pvt->mwisendactive = 1;
11257 } else if (pvt->mwisend_fsk) {
11259 pvt->mwisendactive = 1;
11260 } else {
11261 pvt->mwisendactive = 0;
11262 return 0;
11263 }
11264#else
11265 if (mwisend_rpas) {
11267 } else {
11269 }
11270 pvt->mwisendactive = 1;
11271#endif
11272
11273 if (pvt->cidspill) {
11274 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11275 ast_free(pvt->cidspill);
11276 pvt->cidspill = NULL;
11277 pvt->cidpos = 0;
11278 pvt->cidlen = 0;
11279 }
11281 if (!pvt->cidspill) {
11282 pvt->mwisendactive = 0;
11283 return -1;
11284 }
11285 x = DAHDI_FLUSH_BOTH;
11286 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11287 x = 3000;
11288 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11289#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11290 if (pvt->mwisend_fsk) {
11291#endif
11293 CID_MWI_TYPE_MDMF_FULL, AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11294 pvt->cidpos = 0;
11295#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11296 }
11297#endif
11298 return 0;
11299}
int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct ast_format *codec, const char *name, const char *number, int flags)
Generate message waiting indicator.
Definition: callerid.c:853
#define MAX_CALLERID_SIZE
Definition: callerid.h:50
#define CID_MWI_TYPE_MDMF_FULL
Definition: callerid.h:83
static int mwisend_rpas
Definition: chan_dahdi.c:723
@ MWI_SEND_SA
Definition: chan_dahdi.h:102
@ MWI_SEND_SPILL
Definition: chan_dahdi.h:105
struct mwisend_info mwisend_data
Definition: chan_dahdi.h:480
mwisend_states mwisend_current
Definition: chan_dahdi.h:112

References ast_callerid_vmwi_generate(), ast_calloc, ast_free, AST_LAW, ast_log, CID_MWI_TYPE_MDMF_FULL, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_subchannel::dfd, has_voicemail(), LOG_WARNING, MAX_CALLERID_SIZE, MWI_SEND_SA, MWI_SEND_SPILL, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, mwisend_rpas, dahdi_pvt::mwisendactive, NULL, SUB_REAL, and dahdi_pvt::subs.

Referenced by do_monitor().

◆ mwi_send_process_buffer()

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

Definition at line 11301 of file chan_dahdi.c.

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

References AS_RP_cadence, 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, NULL, mwisend_info::pause, SUB_REAL, and dahdi_pvt::subs.

Referenced by do_monitor().

◆ mwi_send_process_event()

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

Definition at line 11389 of file chan_dahdi.c.

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

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, NULL, mwisend_info::pause, SUB_REAL, and dahdi_pvt::subs.

Referenced by do_monitor().

◆ mwi_thread()

static void * mwi_thread ( void *  data)
static

Definition at line 11091 of file chan_dahdi.c.

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

References analog_ss_thread(), analog_ss_thread_start(), ast_callid_threadstorage_auto(), ast_callid_threadstorage_auto_clean(), 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(), ast_channel::callid, dahdi_pvt::channel, CID_MSGWAITING, CID_NOMSGWAITING, dahdi_pvt::cid_signalling, dahdi_analog_lib_handles(), 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, mwilevel, dahdi_pvt::mwimonitoractive, name, notify_message(), NULL, callerid_state::number, dahdi_pvt::oprmode, mwi_thread_data::pvt, dahdi_pvt::radio, restore_gains(), result, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.

Referenced by do_monitor().

◆ my_all_subchannels_hungup()

static void my_all_subchannels_hungup ( void *  pvt)
static

Definition at line 2251 of file chan_dahdi.c.

2252{
2253 struct dahdi_pvt *p = pvt;
2254 int res, law;
2255
2256 p->faxhandled = 0;
2257 p->didtdd = 0;
2258
2259 if (p->dsp) {
2260 ast_dsp_free(p->dsp);
2261 p->dsp = NULL;
2262 }
2263
2264 p->law = p->law_default;
2265 law = p->law_default;
2266 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2267 if (res < 0)
2268 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2269
2271
2272#if 1
2273 {
2274 int i;
2275 p->owner = NULL;
2276 /* Cleanup owners here */
2277 for (i = 0; i < 3; i++) {
2278 p->subs[i].owner = NULL;
2279 }
2280 }
2281#endif
2282
2283 reset_conf(p);
2284 if (num_restart_pending == 0) {
2286 }
2287}

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, NULL, num_restart_pending, dahdi_subchannel::owner, dahdi_pvt::owner, reset_conf(), restart_monitor(), SUB_REAL, and dahdi_pvt::subs.

◆ my_allocate_sub()

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

Definition at line 2568 of file chan_dahdi.c.

2569{
2570 struct dahdi_pvt *p = pvt;
2571
2572 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
2573}
static int analogsub_to_dahdisub(enum analog_sub analogsub)
Definition: chan_dahdi.c:1253

References alloc_sub(), and analogsub_to_dahdisub().

◆ my_answer_polarityswitch()

static void my_answer_polarityswitch ( void *  pvt)
static

Definition at line 2803 of file chan_dahdi.c.

2804{
2805 struct dahdi_pvt *p = pvt;
2806
2807 if (!p->answeronpolarityswitch) {
2808 return;
2809 }
2810
2811 my_set_polarity(pvt, 1);
2812}
static void my_set_polarity(void *pvt, int value)
Definition: chan_dahdi.c:2783

References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().

◆ my_callwait()

static int my_callwait ( void *  pvt)
static

Definition at line 1652 of file chan_dahdi.c.

1653{
1654 struct dahdi_pvt *p = pvt;
1655
1657 if (p->cidspill) {
1658 ast_log(LOG_WARNING, "Spill already exists?!?\n");
1659 ast_free(p->cidspill);
1660 }
1661
1662 /*
1663 * SAS: Subscriber Alert Signal, 440Hz for 300ms
1664 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
1665 */
1666 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1667 return -1;
1668 save_conference(p);
1669 /* Silence */
1670 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1671 if (!p->callwaitrings && p->callwaitingcallerid) {
1672 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1673 p->callwaitcas = 1;
1674 p->cidlen = 2400 + 680 + READ_SIZE * 4;
1675 } else {
1676 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1677 p->callwaitcas = 0;
1678 p->cidlen = 2400 + READ_SIZE * 4;
1679 }
1680 p->cidpos = 0;
1681 send_callerid(p);
1682
1683 return 0;
1684}

References ast_free, ast_gen_cas(), AST_LAW, ast_log, ast_malloc, dahdi_pvt::callwaitcas, CALLWAITING_REPEAT_SAMPLES, dahdi_pvt::callwaitingcallerid, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, LOG_WARNING, READ_SIZE, save_conference(), and send_callerid().

◆ my_cancel_cidspill()

static void my_cancel_cidspill ( void *  pvt)
static

Definition at line 2201 of file chan_dahdi.c.

2202{
2203 struct dahdi_pvt *p = pvt;
2204
2205 ast_free(p->cidspill);
2206 p->cidspill = NULL;
2208}

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

◆ my_check_confirmanswer()

static int my_check_confirmanswer ( void *  pvt)
static

Definition at line 2184 of file chan_dahdi.c.

2185{
2186 struct dahdi_pvt *p = pvt;
2187 if (p->confirmanswer) {
2188 return 1;
2189 }
2190
2191 return 0;
2192}

References dahdi_pvt::confirmanswer.

◆ my_check_for_conference()

static int my_check_for_conference ( void *  pvt)
static

Definition at line 2361 of file chan_dahdi.c.

2362{
2363 struct dahdi_pvt *p = pvt;
2364 return check_for_conference(p);
2365}

References check_for_conference().

◆ my_check_waitingfordt()

static int my_check_waitingfordt ( void *  pvt)
static

Definition at line 2167 of file chan_dahdi.c.

2168{
2169 struct dahdi_pvt *p = pvt;
2170
2171 if (p->waitingfordt.tv_sec) {
2172 return 1;
2173 }
2174
2175 return 0;
2176}

References dahdi_pvt::waitingfordt.

◆ my_complete_conference_update()

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

Definition at line 2311 of file chan_dahdi.c.

2312{
2313 struct dahdi_pvt *p = pvt;
2314 int needconf = needconference;
2315 int x;
2316 int useslavenative;
2317 struct dahdi_pvt *slave = NULL;
2318
2319 useslavenative = isslavenative(p, &slave);
2320
2321 /* If we have a slave, add him to our conference now. or DAX
2322 if this is slave native */
2323 for (x = 0; x < MAX_SLAVES; x++) {
2324 if (p->slaves[x]) {
2325 if (useslavenative)
2326 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
2327 else {
2328 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
2329 needconf++;
2330 }
2331 }
2332 }
2333 /* If we're supposed to be in there, do so now */
2334 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
2335 if (useslavenative)
2336 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
2337 else {
2338 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
2339 needconf++;
2340 }
2341 }
2342 /* If we have a master, add ourselves to his conference */
2343 if (p->master) {
2344 if (isslavenative(p->master, NULL)) {
2346 } else {
2347 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
2348 }
2349 }
2350 if (!needconf) {
2351 /* Nobody is left (or should be left) in our conference.
2352 Kill it. */
2353 p->confno = -1;
2354 }
2355
2356 return 0;
2357}

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

◆ my_conf_add()

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

Definition at line 2301 of file chan_dahdi.c.

2302{
2303 struct dahdi_pvt *p = pvt;
2304 int x = analogsub_to_dahdisub(sub);
2305
2306 return conf_add(p, &p->subs[x], x, 0);
2307}
struct stasis_forward * sub
Definition: res_corosync.c:240

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

◆ my_conf_del()

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

Definition at line 2291 of file chan_dahdi.c.

2292{
2293 struct dahdi_pvt *p = pvt;
2294 int x = analogsub_to_dahdisub(sub);
2295
2296 return conf_del(p, &p->subs[x], x);
2297}

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

◆ my_confmute()

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

Definition at line 2210 of file chan_dahdi.c.

2211{
2212 struct dahdi_pvt *p = pvt;
2213 return dahdi_confmute(p, mute);
2214}

References dahdi_confmute().

◆ my_dahdi_write()

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

Definition at line 9237 of file chan_dahdi.c.

9238{
9239 int sent=0;
9240 int size;
9241 int res;
9242 int fd;
9243 fd = p->subs[idx].dfd;
9244 while (len) {
9245 size = len;
9246 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
9247 size = (linear ? READ_SIZE * 2 : READ_SIZE);
9248 res = write(fd, buf, size);
9249 if (res != size) {
9250 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
9251 return sent;
9252 }
9253 len -= size;
9254 buf += size;
9255 }
9256 return sent;
9257}

References ast_debug, buf, dahdi_pvt::channel, dahdi_subchannel::dfd, errno, len(), READ_SIZE, and dahdi_pvt::subs.

Referenced by dahdi_write().

◆ my_deadlock_avoidance_private()

static void my_deadlock_avoidance_private ( void *  pvt)
static

Definition at line 1891 of file chan_dahdi.c.

1892{
1893 struct dahdi_pvt *p = pvt;
1894
1896}

References DEADLOCK_AVOIDANCE, and dahdi_pvt::lock.

◆ my_decrease_ss_count()

static void my_decrease_ss_count ( void  )
static

◆ my_dial_digits()

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

Definition at line 2917 of file chan_dahdi.c.

2918{
2919 struct dahdi_pvt *p = pvt;
2920
2921 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
2922 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
2923 return -1;
2924 }
2925
2926 if (sub != ANALOG_SUB_REAL) {
2927 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
2928 dop->dialstr, p->channel, sub);
2929 return -1;
2930 }
2931
2932 return dahdi_dial_str(p, DAHDI_DIAL_OP_REPLACE, dop->dialstr);
2933}
@ ANALOG_DIAL_OP_REPLACE
Definition: sig_analog.h:134

References ANALOG_DIAL_OP_REPLACE, ANALOG_SUB_REAL, ast_log, dahdi_pvt::channel, dahdi_dial_str(), dahdi_pvt::dop, LOG_ERROR, and sub.

◆ my_distinctive_ring()

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

Definition at line 1514 of file chan_dahdi.c.

1515{
1516 unsigned char buf[256];
1517 int distMatches;
1518 int curRingData[RING_PATTERNS];
1519 int receivedRingT;
1520 int counter1;
1521 int counter;
1522 int i;
1523 int res;
1524 int checkaftercid = 0;
1525 const char *matched_context;
1526 struct dahdi_pvt *p = pvt;
1527 struct analog_pvt *analog_p = p->sig_pvt;
1528
1529 if (ringdata == NULL) {
1530 ringdata = curRingData;
1531 } else {
1532 checkaftercid = 1;
1533 }
1534
1535 /* We must have a ring by now so lets try to listen for distinctive ringing */
1536 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
1537 /* Clear the current ring data array so we don't have old data in it. */
1538 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
1539 ringdata[receivedRingT] = 0;
1540 receivedRingT = 0;
1541
1542 if (checkaftercid && distinctiveringaftercid) {
1543 ast_verb(3, "Detecting post-CID distinctive ring\n");
1544 }
1545
1546 for (;;) {
1547 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
1548 res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i);
1549 if (res) {
1550 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
1551 ast_hangup(chan);
1552 return 1;
1553 }
1554 if (i & DAHDI_IOMUX_SIGEVENT) {
1555 res = dahdi_get_event(p->subs[idx].dfd);
1556 ast_debug(3, "Got event %d (%s)...\n", res, event2str(res));
1557 if (res == DAHDI_EVENT_NOALARM) {
1558 p->inalarm = 0;
1559 analog_p->inalarm = 0;
1560 } else if (res == DAHDI_EVENT_RINGOFFHOOK) {
1561 /* Let us detect distinctive ring */
1562 ringdata[receivedRingT] = analog_p->ringt;
1563
1564 if (analog_p->ringt < analog_p->ringt_base / 2) {
1565 break;
1566 }
1567 /* Increment the ringT counter so we can match it against
1568 values in chan_dahdi.conf for distinctive ring */
1569 if (++receivedRingT == RING_PATTERNS) {
1570 break;
1571 }
1572 }
1573 } else if (i & DAHDI_IOMUX_READ) {
1574 res = read(p->subs[idx].dfd, buf, sizeof(buf));
1575 if (res < 0) {
1576 if (errno != ELAST) {
1577 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1578 ast_hangup(chan);
1579 return 1;
1580 }
1581 break;
1582 }
1583 if (analog_p->ringt > 0) {
1584 if (!(--analog_p->ringt)) {
1585 break;
1586 }
1587 }
1588 }
1589 }
1590 }
1591
1592 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
1593 ast_verb(3, "Detected ring pattern: %d,%d,%d\n", ringdata[0], ringdata[1], ringdata[2]);
1594 matched_context = p->defcontext;
1595 for (counter = 0; counter < 3; counter++) {
1596 int range = p->drings.ringnum[counter].range;
1597
1598 distMatches = 0;
1599 ast_verb(3, "Checking %d,%d,%d with +/- %d range\n",
1600 p->drings.ringnum[counter].ring[0],
1601 p->drings.ringnum[counter].ring[1],
1602 p->drings.ringnum[counter].ring[2],
1603 range);
1604 for (counter1 = 0; counter1 < 3; counter1++) {
1605 int ring = p->drings.ringnum[counter].ring[counter1];
1606
1607 if (ring == -1) {
1608 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
1609 ringdata[counter1]);
1610 distMatches++;
1611 } else if (ring - range <= ringdata[counter1] && ringdata[counter1] <= ring + range) {
1612 ast_verb(3, "Ring pattern %d is in range: %d to %d\n",
1613 ringdata[counter1], ring - range, ring + range);
1614 distMatches++;
1615 } else {
1616 /* The current dring pattern cannot match. */
1617 break;
1618 }
1619 }
1620
1621 if (distMatches == 3) {
1622 /* The ring matches, set the context to whatever is for distinctive ring.. */
1623 matched_context = S_OR(p->drings.ringContext[counter].contextData, p->defcontext);
1624 ast_verb(3, "Matched Distinctive Ring context %s\n", matched_context);
1625 break;
1626 }
1627 }
1628
1629 /* Set selected distinctive ring context if not already set. */
1630 if (strcmp(p->context, matched_context) != 0) {
1631 ast_copy_string(p->context, matched_context, sizeof(p->context));
1632 ast_channel_context_set(chan, matched_context);
1633 }
1634
1635 return 0;
1636}
#define RING_PATTERNS
Definition: sig_analog.h:35

References ast_channel_context_set(), ast_copy_string(), ast_debug, ast_hangup(), ast_log, ast_verb, buf, dahdi_pvt::context, ringContextData::contextData, dahdi_get_event(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, distinctiveringaftercid, dahdi_pvt::drings, errno, event2str(), dahdi_pvt::inalarm, analog_pvt::inalarm, LOG_WARNING, NULL, distRingData::range, 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.

◆ my_dsp_reset_and_flush_digits()

static int my_dsp_reset_and_flush_digits ( void *  pvt)
static

Definition at line 1739 of file chan_dahdi.c.

1740{
1741 struct dahdi_pvt *p = pvt;
1742 if (p->dsp)
1744
1745 return 0;
1746}

References ast_dsp_digitreset(), and dahdi_pvt::dsp.

◆ my_dsp_set_digitmode()

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

Definition at line 1748 of file chan_dahdi.c.

1749{
1750 struct dahdi_pvt *p = pvt;
1751
1752 if (p->channel == CHAN_PSEUDO)
1753 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
1754
1755 if (mode == ANALOG_DIGITMODE_DTMF) {
1756 /* If we do hardware dtmf, no need for a DSP */
1757 if (p->hardwaredtmf) {
1758 if (p->dsp) {
1759 ast_dsp_free(p->dsp);
1760 p->dsp = NULL;
1761 }
1762 return 0;
1763 }
1764
1765 if (!p->dsp) {
1766 p->dsp = ast_dsp_new();
1767 if (!p->dsp) {
1768 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1769 return -1;
1770 }
1771 }
1772
1774 } else if (mode == ANALOG_DIGITMODE_MF) {
1775 if (!p->dsp) {
1776 p->dsp = ast_dsp_new();
1777 if (!p->dsp) {
1778 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1779 return -1;
1780 }
1781 }
1783 }
1784 return 0;
1785}
@ ANALOG_DIGITMODE_DTMF
Definition: sig_analog.h:115
@ ANALOG_DIGITMODE_MF
Definition: sig_analog.h:116

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, LOG_ERROR, and NULL.

◆ my_flash()

static int my_flash ( void *  pvt)
static

Definition at line 2762 of file chan_dahdi.c.

2763{
2764 struct dahdi_pvt *p = pvt;
2765 int func = DAHDI_FLASH;
2766 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
2767}

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

◆ my_get_and_handle_alarms()

static void my_get_and_handle_alarms ( void *  pvt)
static

Definition at line 2015 of file chan_dahdi.c.

2016{
2017 int res;
2018 struct dahdi_pvt *p = pvt;
2019
2020 res = get_alarms(p);
2021 handle_alarms(p, res);
2022}

References get_alarms(), and handle_alarms().

◆ my_get_callerid()

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

Definition at line 1429 of file chan_dahdi.c.

1430{
1431 struct dahdi_pvt *p = pvt;
1432 struct analog_pvt *analog_p = p->sig_pvt;
1433 struct pollfd poller;
1434 char *name, *num;
1435 int index = SUB_REAL;
1436 int res;
1437 unsigned char buf[256];
1438 int flags;
1439
1440 poller.fd = p->subs[SUB_REAL].dfd;
1441 poller.events = POLLPRI | POLLIN;
1442 poller.revents = 0;
1443
1444 res = poll(&poller, 1, timeout);
1445
1446 if (poller.revents & POLLPRI) {
1448 return 1;
1449 }
1450
1451 if (poller.revents & POLLIN) {
1452 /*** NOTES ***/
1453 /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
1454 * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
1455 * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
1456 * a failure and die, and returning 2 means no event was received. */
1457 res = read(p->subs[index].dfd, buf, sizeof(buf));
1458 if (res < 0) {
1459 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1460 return -1;
1461 }
1462
1463 if (analog_p->ringt > 0) {
1464 if (!(--analog_p->ringt)) {
1465 /* only return if we timeout from a ring event */
1466 return -1;
1467 }
1468 }
1469
1470 if (p->cid_signalling == CID_SIG_V23_JP) {
1471 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
1472 } else {
1473 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
1474 }
1475 if (res < 0) {
1476 /*
1477 * The previous diagnostic message output likely
1478 * explains why it failed.
1479 */
1480 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
1481 return -1;
1482 }
1483
1484 if (res == 1) {
1485 callerid_get(p->cs, &name, &num, &flags);
1486 if (name)
1488 if (num)
1489 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
1490
1491 if (flags & (CID_PRIVATE_NUMBER | CID_UNKNOWN_NUMBER)) {
1492 /* If we got a presentation, we must set it on the channel */
1493 struct ast_channel *chan = analog_p->ss_astchan;
1494 struct ast_party_caller caller;
1495
1497 caller.id.name.presentation = caller.id.number.presentation = (flags & CID_PRIVATE_NUMBER) ?
1500 ast_party_caller_free(&caller);
1501 }
1502
1503 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
1504 return 0;
1505 }
1506 }
1507
1508 *ev = ANALOG_EVENT_NONE;
1509 return 2;
1510}
#define CID_UNKNOWN_NUMBER
Definition: callerid.h:55
#define AST_PRES_USER_NUMBER_UNSCREENED
Definition: callerid.h:412
#define AST_PRES_UNAVAILABLE
Definition: callerid.h:420
#define AST_PRES_RESTRICTED
Definition: callerid.h:419
#define CID_PRIVATE_NUMBER
Definition: callerid.h:53
void ast_party_caller_set(struct ast_party_caller *dest, const struct ast_party_caller *src, const struct ast_set_party_caller *update)
Set the caller information based on another caller source.
Definition: channel.c:2007
void ast_party_caller_set_init(struct ast_party_caller *init, const struct ast_party_caller *guide)
Initialize the given caller structure using the given guide for a set update operation.
Definition: channel.c:1999
void ast_party_caller_free(struct ast_party_caller *doomed)
Destroy the caller party contents.
Definition: channel.c:2015
#define ANALOG_MAX_CID
Definition: sig_analog.h:33
@ ANALOG_EVENT_NONE
Definition: sig_analog.h:80
struct ast_channel * ss_astchan
Definition: sig_analog.h:372
Caller Party information.
Definition: channel.h:418
struct callerid_state * cs
Definition: chan_dahdi.h:126

References ANALOG_EVENT_NONE, ANALOG_MAX_CID, ast_channel_caller(), ast_copy_string(), ast_debug, AST_LAW, ast_log, ast_party_caller_free(), ast_party_caller_set(), ast_party_caller_set_init(), AST_PRES_RESTRICTED, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_UNSCREENED, buf, callerid_feed(), callerid_feed_jp(), callerid_get(), CID_PRIVATE_NUMBER, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, CID_UNKNOWN_NUMBER, dahdi_pvt::cs, dahdi_get_event(), dahdievent_to_analogevent(), dahdi_subchannel::dfd, errno, ast_party_caller::id, LOG_WARNING, name, ast_party_id::name, NULL, ast_party_id::number, ast_party_name::presentation, ast_party_number::presentation, analog_pvt::ringt, dahdi_pvt::sig_pvt, analog_pvt::ss_astchan, SUB_REAL, and dahdi_pvt::subs.

◆ my_get_event()

static int my_get_event ( void *  pvt)
static

Definition at line 2698 of file chan_dahdi.c.

2699{
2700 struct dahdi_pvt *p = pvt;
2701 int res;
2702
2703 if (p->fake_event) {
2704 res = p->fake_event;
2705 p->fake_event = 0;
2706 } else
2707 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
2708
2709 return dahdievent_to_analogevent(res);
2710}

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

◆ my_get_orig_dialstring()

static const char * my_get_orig_dialstring ( void *  pvt)
static

Definition at line 2229 of file chan_dahdi.c.

2230{
2231 struct dahdi_pvt *p = pvt;
2232
2233 return p->dialstring;
2234}

References dahdi_pvt::dialstring.

◆ my_get_sigpvt_bridged_channel()

static void * my_get_sigpvt_bridged_channel ( struct ast_channel chan)
static

Definition at line 2024 of file chan_dahdi.c.

2025{
2027
2028 if (bridged && ast_channel_tech(bridged) == &dahdi_tech) {
2029 struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
2030
2031 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
2032 return p->sig_pvt;
2033 }
2034 }
2035 return NULL;
2036}

References ast_channel_bridge_peer(), ast_channel_cleanup, ast_channel_tech(), ast_channel_tech_pvt(), dahdi_analog_lib_handles(), dahdi_tech, NULL, dahdi_pvt::oprmode, dahdi_pvt::radio, RAII_VAR, dahdi_pvt::sig, and dahdi_pvt::sig_pvt.

◆ my_get_sub_fd()

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

Definition at line 2038 of file chan_dahdi.c.

2039{
2040 struct dahdi_pvt *p = pvt;
2041 int dahdi_sub = analogsub_to_dahdisub(sub);
2042 return p->subs[dahdi_sub].dfd;
2043}

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

◆ my_getsigstr()

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

Definition at line 9765 of file chan_dahdi.c.

9766{
9767 char c;
9768
9769 *str = 0; /* start with empty output buffer */
9770 for (;;)
9771 {
9772 /* Wait for the first digit (up to specified ms). */
9773 c = ast_waitfordigit(chan, ms);
9774 /* if timeout, hangup or error, return as such */
9775 if (c < 1)
9776 return c;
9777 *str++ = c;
9778 *str = 0;
9779 if (strchr(term, c))
9780 return 1;
9781 }
9782}
const char * str
Definition: app_jack.c:147

References ast_waitfordigit(), c, and str.

Referenced by analog_ss_thread().

◆ my_handle_dtmf()

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

Definition at line 1805 of file chan_dahdi.c.

1806{
1807 struct ast_frame *f = *dest;
1808 struct dahdi_pvt *p = pvt;
1809 int idx = analogsub_to_dahdisub(analog_index);
1810
1811 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
1812 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
1813 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
1814
1815 if (f->subclass.integer == 'f') {
1816 if (f->frametype == AST_FRAME_DTMF_END) {
1817 /* Fax tone -- Handle and return NULL */
1818 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
1819 /* If faxbuffers are configured, use them for the fax transmission */
1820 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
1821 struct dahdi_bufferinfo bi = {
1822 .txbufpolicy = p->faxbuf_policy,
1823 .bufsize = p->bufsize,
1824 .numbufs = p->faxbuf_no
1825 };
1826 int res;
1827
1828 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
1829 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
1830 } else {
1831 p->bufferoverrideinuse = 1;
1832 }
1833 }
1834 p->faxhandled = 1;
1835 if (p->dsp) {
1836 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
1838 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
1839 }
1840 if (strcmp(ast_channel_exten(ast), "fax")) {
1841 const char *target_context = ast_channel_context(ast);
1842
1843 /*
1844 * We need to unlock 'ast' here because ast_exists_extension has the
1845 * potential to start autoservice on the channel. Such action is prone
1846 * to deadlock if the channel is locked.
1847 *
1848 * ast_async_goto() has its own restriction on not holding the
1849 * channel lock.
1850 */
1852 ast_channel_unlock(ast);
1853 if (ast_exists_extension(ast, target_context, "fax", 1,
1854 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
1855 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
1856 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
1857 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
1858 if (ast_async_goto(ast, target_context, "fax", 1))
1859 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
1860 } else {
1861 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
1862 }
1863 ast_channel_lock(ast);
1864 ast_mutex_lock(&p->lock);
1865 } else {
1866 ast_debug(1, "Already in a fax extension, not redirecting\n");
1867 }
1868 } else {
1869 ast_debug(1, "Fax already handled\n");
1870 }
1871 dahdi_confmute(p, 0);
1872 }
1873 p->subs[idx].f.frametype = AST_FRAME_NULL;
1874 p->subs[idx].f.subclass.integer = 0;
1875 *dest = &p->subs[idx].f;
1876 }
1877}

References analogsub_to_dahdisub(), ast_async_goto(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), 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, dahdi_pvt::callprogress, CALLPROGRESS_FAX, dahdi_confmute(), dahdi_subchannel::dfd, dahdi_pvt::dsp, dahdi_pvt::dsp_features, errno, dahdi_subchannel::f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxhandled, ast_frame::frametype, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, NULL, pbx_builtin_setvar_helper(), S_COR, ast_frame::subclass, dahdi_pvt::subs, and dahdi_pvt::usefaxbuffers.

◆ my_handle_notify_message()

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

Definition at line 3556 of file chan_dahdi.c.

3557{
3558 struct dahdi_pvt *p = pvt;
3559
3560 if (neon_mwievent > -1 && !p->mwimonitor_neon)
3561 return;
3562
3563 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
3564 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
3565 notify_message(p->mailbox, 1);
3566 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
3567 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
3568 notify_message(p->mailbox, 0);
3569 }
3570 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
3571 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
3572 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
3573 ast_hangup(chan);
3574 return;
3575 }
3576}
unsigned int mwimonitor_rpas
TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
Definition: chan_dahdi.h:429

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

◆ my_hangup_polarityswitch()

static void my_hangup_polarityswitch ( void *  pvt)
static

Definition at line 2814 of file chan_dahdi.c.

2815{
2816 struct dahdi_pvt *p = pvt;
2817
2818 if (!p->hanguponpolarityswitch) {
2819 return;
2820 }
2821
2822 if (p->answeronpolarityswitch) {
2823 my_set_polarity(pvt, 0);
2824 } else {
2825 my_set_polarity(pvt, 1);
2826 }
2827}

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

◆ my_has_voicemail()

static int my_has_voicemail ( void *  pvt)
static

Definition at line 2577 of file chan_dahdi.c.

2578{
2579 struct dahdi_pvt *p = pvt;
2580
2581 return has_voicemail(p);
2582}

References has_voicemail().

◆ my_have_progressdetect()

static int my_have_progressdetect ( void *  pvt)
static

Definition at line 3578 of file chan_dahdi.c.

3579{
3580 struct dahdi_pvt *p = pvt;
3581
3583 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3584 return 1;
3585 } else {
3586 /* Don't have progress detection. */
3587 return 0;
3588 }
3589}

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

◆ my_increase_ss_count()

static void my_increase_ss_count ( void  )
static

◆ my_is_dialing()

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

Definition at line 2946 of file chan_dahdi.c.

2947{
2948 struct dahdi_pvt *p = pvt;
2949 int index;
2950 int x;
2951
2952 index = analogsub_to_dahdisub(sub);
2953
2954 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
2955 ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
2956 return -1;
2957 }
2958
2959 return x;
2960}

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

◆ my_is_off_hook()

static int my_is_off_hook ( void *  pvt)
static

Definition at line 2712 of file chan_dahdi.c.

2713{
2714 struct dahdi_pvt *p = pvt;
2715 int res;
2716 struct dahdi_params par;
2717
2718 memset(&par, 0, sizeof(par));
2719
2720 if (p->subs[SUB_REAL].dfd > -1)
2721 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2722 else {
2723 /* Assume not off hook on CVRS */
2724 res = 0;
2725 par.rxisoffhook = 0;
2726 }
2727 if (res) {
2728 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
2729 }
2730
2731 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
2732 /* When "onhook" that means no battery on the line, and thus
2733 it is out of service..., if it's on a TDM card... If it's a channel
2734 bank, there is no telling... */
2735 return (par.rxbits > -1) || par.rxisoffhook;
2736 }
2737
2738 return par.rxisoffhook;
2739}

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.

Referenced by dahdi_hangup(), and do_monitor().

◆ my_lock_private()

static void my_lock_private ( void *  pvt)
static

Definition at line 1879 of file chan_dahdi.c.

1880{
1881 struct dahdi_pvt *p = pvt;
1882 ast_mutex_lock(&p->lock);
1883}

References ast_mutex_lock, and dahdi_pvt::lock.

◆ my_new_analog_ast_channel()

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

Definition at line 2411 of file chan_dahdi.c.

2412{
2413 ast_callid callid = 0;
2414 int callid_created = ast_callid_threadstorage_auto(&callid);
2415 struct dahdi_pvt *p = pvt;
2416 int dsub = analogsub_to_dahdisub(sub);
2417
2418 return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, NULL, requestor, callid, callid_created);
2419}
static struct ast_channel * dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid, int callid_created)
Definition: chan_dahdi.c:9509

References analogsub_to_dahdisub(), ast_callid_threadstorage_auto(), ast_channel::callid, dahdi_new_callid_clean(), NULL, and sub.

◆ my_off_hook()

static int my_off_hook ( void *  pvt)
static

Definition at line 2771 of file chan_dahdi.c.

2772{
2773 struct dahdi_pvt *p = pvt;
2774 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2775}

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

Referenced by dahdi_hangup().

◆ my_on_hook()

static int my_on_hook ( void *  pvt)
static

Definition at line 2962 of file chan_dahdi.c.

2963{
2964 struct dahdi_pvt *p = pvt;
2965 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
2966}

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

◆ my_play_tone()

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

Definition at line 2584 of file chan_dahdi.c.

2585{
2586 struct dahdi_pvt *p = pvt;
2587 int index;
2588
2589 index = analogsub_to_dahdisub(sub);
2590
2591 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
2592}
static int analog_tone_to_dahditone(enum analog_tone tone)
Definition: chan_dahdi.c:1233

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

Referenced by dahdi_hangup().

◆ my_ring()

static int my_ring ( void *  pvt)
static

Definition at line 2755 of file chan_dahdi.c.

2756{
2757 struct dahdi_pvt *p = pvt;
2758
2759 return dahdi_ring_phone(p);
2760}

References dahdi_ring_phone().

◆ my_send_callerid()

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

Definition at line 1686 of file chan_dahdi.c.

1687{
1688 struct dahdi_pvt *p = pvt;
1689 struct analog_pvt *analog_p = p->sig_pvt;
1690
1691 ast_debug(2, "Starting cid spill\n");
1692
1693 if (p->cidspill) {
1694 ast_log(LOG_WARNING, "cidspill already exists??\n");
1695 ast_free(p->cidspill);
1696 }
1697
1699 int pres = ast_party_id_presentation(&caller->id);
1700 if (cwcid == 0) {
1701 /* Some CPE support additional parameters for on-hook Caller*ID,
1702 * such as redirecting reason and call qualifier, so send those
1703 * if available.
1704 * I don't know of any CPE that supports this for Call Waiting (unfortunately),
1705 * so don't send those for call waiting as that will just lengthen the CID spill
1706 * for no good reason.
1707 */
1709 caller->id.name.str,
1711 NULL,
1712 analog_p->redirecting_reason,
1713 pres,
1714 analog_p->call_qualifier,
1716 AST_LAW(p));
1717 } else {
1718 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
1720 p->callwaitcas = 0;
1721 p->cidcwexpire = 0;
1723 caller->id.name.str,
1725 NULL,
1726 -1,
1727 pres,
1728 0,
1729 AST_LAW(p));
1730 p->cidlen += READ_SIZE * 4;
1731 }
1732 p->cidpos = 0;
1733 p->cid_suppress_expire = 0;
1734 send_callerid(p);
1735 }
1736 return 0;
1737}
int ast_callerid_callwaiting_full_generate(unsigned char *buf, const char *name, const char *number, const char *ddn, int redirecting, int pres, int qualifier, struct ast_format *codec)
Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)
Definition: callerid.c:1154
#define CID_TYPE_MDMF
Definition: callerid.h:75
int ast_callerid_full_generate(unsigned char *buf, const char *name, const char *number, const char *ddn, int redirecting, int pres, int qualifier, int format, struct ast_format *codec)
Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format)
Definition: callerid.c:1148
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:1821
int redirecting_reason
Definition: sig_analog.h:356
unsigned int call_qualifier
Definition: sig_analog.h:349
struct ast_party_caller caller
Definition: sig_analog.h:355

References ast_callerid_callwaiting_full_generate(), ast_callerid_full_generate(), ast_debug, ast_free, AST_LAW, ast_log, ast_malloc, ast_party_id_presentation(), ast_verb, analog_pvt::call_qualifier, analog_pvt::caller, dahdi_pvt::callwaitcas, dahdi_pvt::cid_suppress_expire, CID_TYPE_MDMF, 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, NULL, ast_party_id::number, READ_SIZE, analog_pvt::redirecting_reason, send_callerid(), dahdi_pvt::sig_pvt, ast_party_name::str, and ast_party_number::str.

◆ my_set_alarm()

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

Definition at line 2064 of file chan_dahdi.c.

2065{
2066 struct dahdi_pvt *p = pvt;
2067
2068 p->inalarm = in_alarm;
2069}

References dahdi_pvt::inalarm.

◆ my_set_cadence()

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

Definition at line 2045 of file chan_dahdi.c.

2046{
2047 struct dahdi_pvt *p = pvt;
2048
2049 /* Choose proper cadence */
2050 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
2051 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
2052 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
2053 *cid_rings = cidrings[p->distinctivering - 1];
2054 } else {
2055 if (p->distinctivering > 0) {
2056 ast_log(LOG_WARNING, "Cadence %d is not defined, falling back to default ring cadence\n", p->distinctivering);
2057 }
2058 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
2059 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
2060 *cid_rings = p->sendcalleridafter;
2061 }
2062}
int sendcalleridafter
Send caller ID on FXS after this many rings. Set to 1 for US.
Definition: chan_dahdi.h:734

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

◆ my_set_callwaiting()

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

Definition at line 2194 of file chan_dahdi.c.

2195{
2196 struct dahdi_pvt *p = pvt;
2197
2198 p->callwaiting = callwaiting_enable;
2199}

References dahdi_pvt::callwaiting.

◆ my_set_confirmanswer()

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

Definition at line 2178 of file chan_dahdi.c.

2179{
2180 struct dahdi_pvt *p = pvt;
2181 p->confirmanswer = flag;
2182}

References dahdi_pvt::confirmanswer.

◆ my_set_dialing()

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

Definition at line 2071 of file chan_dahdi.c.

2072{
2073 struct dahdi_pvt *p = pvt;
2074
2075 p->dialing = is_dialing;
2076}

References dahdi_pvt::dialing.

◆ my_set_echocanceller()

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

Definition at line 2741 of file chan_dahdi.c.

2742{
2743 struct dahdi_pvt *p = pvt;
2744
2745 if (enable)
2746 dahdi_ec_enable(p);
2747 else
2749
2750 return 0;
2751}

References dahdi_ec_disable(), and dahdi_ec_enable().

◆ my_set_inthreeway()

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

Definition at line 2005 of file chan_dahdi.c.

2006{
2007 struct dahdi_pvt *p = pvt;
2008 int idx = analogsub_to_dahdisub(sub);
2009
2010 p->subs[idx].inthreeway = inthreeway;
2011}

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

◆ my_set_linear_mode()

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

Definition at line 1993 of file chan_dahdi.c.

1994{
1995 struct dahdi_pvt *p = pvt;
1996 int oldval;
1997 int idx = analogsub_to_dahdisub(sub);
1998
1999 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
2000 oldval = p->subs[idx].linear;
2001 p->subs[idx].linear = linear_mode ? 1 : 0;
2002 return oldval;
2003}

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

◆ my_set_needringing()

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

Definition at line 2777 of file chan_dahdi.c.

2778{
2779 struct dahdi_pvt *p = pvt;
2781}

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

◆ my_set_new_owner()

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

Definition at line 2222 of file chan_dahdi.c.

2223{
2224 struct dahdi_pvt *p = pvt;
2225
2226 p->owner = new_owner;
2227}

References dahdi_pvt::owner.

◆ my_set_outgoing()

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

Definition at line 2078 of file chan_dahdi.c.

2079{
2080 struct dahdi_pvt *p = pvt;
2081
2082 p->outgoing = is_outgoing;
2083}

References dahdi_pvt::outgoing.

◆ my_set_polarity()

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

Definition at line 2783 of file chan_dahdi.c.

2784{
2785 struct dahdi_pvt *p = pvt;
2786
2787 if (p->channel == CHAN_PSEUDO) {
2788 return;
2789 }
2790 p->polarity = value;
2791 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
2792}

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

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

◆ my_set_pulsedial()

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

Definition at line 2216 of file chan_dahdi.c.

2217{
2218 struct dahdi_pvt *p = pvt;
2219 p->pulsedial = flag;
2220}

References dahdi_pvt::pulsedial.

◆ my_set_ringtimeout()

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

Definition at line 2121 of file chan_dahdi.c.

2122{
2123 struct dahdi_pvt *p = pvt;
2124 p->ringt = ringt;
2125}

References dahdi_pvt::ringt.

◆ my_set_waitingfordt()

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

Definition at line 2127 of file chan_dahdi.c.

2128{
2129 struct dahdi_pvt *p = pvt;
2130
2131 /* We reset p->waitfordialtonetemp here, to prevent leaking to future calls,
2132 * but we also need to check against this value until we get dialtone
2133 * or the timer expires, since waitingfordt is when the timer started,
2134 * not when it should expire.
2135 *
2136 * Critically, we only set p->waitingfordt here if waitfordialtone or waitfordialtonetemp
2137 * has already been set, as waitingfordt is what is checked at runtime to determine
2138 * if we should be waiting for dial tone. This ensures that if a second call
2139 * is initiated concurrently, the first one "consumes" waitfordialtonetemp and resets it,
2140 * preventing leaking to other calls while remaining available to check on the first one while dialing.
2141 */
2143 p->waitfordialtonetemp = 0;
2144
2146 return;
2147 }
2148
2149 /* Because the DSP is allocated when the channel is created,
2150 * if we requested waitfordialtone later (in a predial handler),
2151 * we need to create it now */
2152 if (!p->dsp) {
2153 p->dsp = ast_dsp_new();
2154 if (!p->dsp) {
2155 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
2156 return;
2157 }
2158 }
2161
2162 ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtoneduration);
2163 gettimeofday(&p->waitingfordt, NULL);
2165}
@ AST_STATE_OFFHOOK
Definition: channelstate.h:38

References ast_debug, ast_dsp_new(), ast_dsp_set_features(), ast_log, ast_setstate(), AST_STATE_OFFHOOK, CANPROGRESSDETECT, dahdi_pvt::dsp, DSP_FEATURE_WAITDIALTONE, dahdi_pvt::dsp_features, LOG_ERROR, NULL, dahdi_pvt::waitfordialtone, dahdi_pvt::waitfordialtoneduration, dahdi_pvt::waitfordialtonetemp, and dahdi_pvt::waitingfordt.

◆ my_start()

static int my_start ( void *  pvt)
static

Definition at line 2909 of file chan_dahdi.c.

2910{
2911 struct dahdi_pvt *p = pvt;
2912 int x = DAHDI_START;
2913
2914 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2915}

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

◆ my_start_cid_detect()

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

Definition at line 1396 of file chan_dahdi.c.

1397{
1398 struct dahdi_pvt *p = pvt;
1399 int index = SUB_REAL;
1401 if (!p->cs) {
1402 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
1403 return -1;
1404 }
1405 bump_gains(p);
1406 dahdi_setlinear(p->subs[index].dfd, 0);
1407
1408 return 0;
1409}

References ast_log, bump_gains(), callerid_new(), dahdi_pvt::cid_signalling, dahdi_pvt::cs, dahdi_setlinear(), dahdi_subchannel::dfd, LOG_ERROR, SUB_REAL, and dahdi_pvt::subs.

◆ my_start_polarityswitch()

static void my_start_polarityswitch ( void *  pvt)
static

Definition at line 2794 of file chan_dahdi.c.

2795{
2796 struct dahdi_pvt *p = pvt;
2797
2799 my_set_polarity(pvt, 0);
2800 }
2801}

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

◆ my_stop_callwait()

static int my_stop_callwait ( void *  pvt)
static

Definition at line 1638 of file chan_dahdi.c.

1639{
1640 struct dahdi_pvt *p = pvt;
1641 p->callwaitingrepeat = 0;
1642 p->cidcwexpire = 0;
1643 p->cid_suppress_expire = 0;
1644
1645 return 0;
1646}

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

◆ my_stop_cid_detect()

static int my_stop_cid_detect ( void *  pvt)
static

Definition at line 1413 of file chan_dahdi.c.

1414{
1415 struct dahdi_pvt *p = pvt;
1416 int index = SUB_REAL;
1417
1418 if (p->cs) {
1419 callerid_free(p->cs);
1420 }
1421
1422 /* Restore linear mode after Caller*ID processing */
1423 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
1424 restore_gains(p);
1425
1426 return 0;
1427}

References callerid_free(), dahdi_pvt::cs, dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_subchannel::linear, restore_gains(), SUB_REAL, and dahdi_pvt::subs.

◆ my_swap_subchannels()

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

2368{
2369 struct dahdi_pvt *p = pvt;
2370 int da, db;
2371 int tchan;
2372 int tinthreeway;
2373
2376
2377 tchan = p->subs[da].chan;
2378 p->subs[da].chan = p->subs[db].chan;
2379 p->subs[db].chan = tchan;
2380
2381 tinthreeway = p->subs[da].inthreeway;
2382 p->subs[da].inthreeway = p->subs[db].inthreeway;
2383 p->subs[db].inthreeway = tinthreeway;
2384
2385 p->subs[da].owner = ast_a;
2386 p->subs[db].owner = ast_b;
2387
2388 if (ast_a)
2389 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
2390 if (ast_b)
2391 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
2392
2393 wakeup_sub(p, a);
2394 wakeup_sub(p, b);
2395
2396 return;
2397}
static sqlite3 * db
static void wakeup_sub(struct dahdi_pvt *p, int a)
Definition: chan_dahdi.c:3728
static struct test_val b

References a, analogsub_to_dahdisub(), ast_channel_set_fd(), b, dahdi_subchannel::chan, db, dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().

◆ my_train_echocanceller()

static int my_train_echocanceller ( void *  pvt)
static

Definition at line 2937 of file chan_dahdi.c.

2938{
2939 struct dahdi_pvt *p = pvt;
2940
2941 dahdi_train_ec(p);
2942
2943 return 0;
2944}

References dahdi_train_ec().

◆ my_unallocate_sub()

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

Definition at line 2559 of file chan_dahdi.c.

2560{
2561 struct dahdi_pvt *p = pvt;
2562
2563 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
2564}

References analogsub_to_dahdisub(), and unalloc_sub().

◆ my_unlock_private()

static void my_unlock_private ( void *  pvt)
static

Definition at line 1885 of file chan_dahdi.c.

1886{
1887 struct dahdi_pvt *p = pvt;
1889}

References ast_mutex_unlock, and dahdi_pvt::lock.

◆ my_wait_event()

static int my_wait_event ( void *  pvt)
static

Definition at line 2691 of file chan_dahdi.c.

2692{
2693 struct dahdi_pvt *p = pvt;
2694
2695 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
2696}

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

◆ my_wink()

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

Definition at line 1789 of file chan_dahdi.c.

1790{
1791 struct dahdi_pvt *p = pvt;
1792 int index = analogsub_to_dahdisub(sub);
1793 if (index != SUB_REAL) {
1794 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
1795 }
1796 return dahdi_wink(p, index);
1797}

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

◆ notify_message()

static void notify_message ( char *  mailbox,
int  thereornot 
)
static

Send MWI state change.

Parameters
mailboxThis is the mailbox associated with the FXO line that the MWI state has changed on.
thereornotThis argument should simply be set to 1 or 0, to indicate whether there are messages waiting or not.

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

3542{
3543 char s[sizeof(mwimonitornotify) + 164];
3544
3545 if (ast_strlen_zero(mailbox)) {
3546 return;
3547 }
3548
3549 ast_publish_mwi_state(mailbox, NULL, thereornot, thereornot);
3551 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
3552 ast_safe_system(s);
3553 }
3554}
static char mwimonitornotify[PATH_MAX]
Definition: chan_dahdi.c:721
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
#define ast_publish_mwi_state(mailbox, context, new_msgs, old_msgs)
Publish a MWI state update via stasis.
Definition: mwi.h:378

References ast_publish_mwi_state, ast_safe_system(), ast_strlen_zero(), voicemailpwcheck::mailbox, mwimonitornotify, and NULL.

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

◆ parse_buffers_policy()

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

Definition at line 7190 of file chan_dahdi.c.

7191{
7192 int res;
7193 char policy_str[21] = "";
7194
7195 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
7196 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
7197 return 1;
7198 }
7199 if (*num_buffers < 0) {
7200 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
7201 return -1;
7202 }
7203 if (!strcasecmp(policy_str, "full")) {
7204 *policy = DAHDI_POLICY_WHEN_FULL;
7205 } else if (!strcasecmp(policy_str, "immediate")) {
7206 *policy = DAHDI_POLICY_IMMEDIATE;
7207#if defined(HAVE_DAHDI_HALF_FULL)
7208 } else if (!strcasecmp(policy_str, "half")) {
7209 *policy = DAHDI_POLICY_HALF_FULL;
7210#endif
7211 } else {
7212 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
7213 return -1;
7214 }
7215
7216 return 0;
7217}

References ast_log, and LOG_WARNING.

Referenced by dahdi_func_write(), and process_dahdi().

◆ parse_busy_pattern()

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

Definition at line 18424 of file chan_dahdi.c.

18425{
18426 int count_pattern = 0;
18427 int norval = 0;
18428 char *temp = NULL;
18429
18430 for (; ;) {
18431 /* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
18432 if (!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
18433 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18434 break;
18435 }
18436
18437 busy_cadence->pattern[count_pattern] = norval;
18438
18439 count_pattern++;
18440 if (count_pattern == 4) {
18441 break;
18442 }
18443
18444 temp = strchr(v->value, ',');
18445 if (temp == NULL) {
18446 break;
18447 }
18448 v->value = temp + 1;
18449 }
18450 busy_cadence->length = count_pattern;
18451
18452 if (count_pattern % 2 != 0) {
18453 /* The pattern length must be divisible by two */
18454 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18455 }
18456
18457}
int pattern[4]
Definition: dsp.h:68

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

Referenced by process_dahdi().

◆ polarity_read()

static int polarity_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buffer,
size_t  buflen 
)
static

Definition at line 2862 of file chan_dahdi.c.

2863{
2864 struct dahdi_pvt *pvt;
2865
2866 pvt = fxo_pvt(chan);
2867 if (!pvt) {
2868 return -1;
2869 }
2870
2871 snprintf(buffer, buflen, "%d", pvt->polarity);
2872
2873 return 0;
2874}
static struct dahdi_pvt * fxo_pvt(struct ast_channel *chan)
Return DAHDI pivot if channel is FXO signalled.
Definition: chan_dahdi.c:2830

References fxo_pvt(), and dahdi_pvt::polarity.

◆ polarity_write()

static int polarity_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
)
static

Definition at line 2876 of file chan_dahdi.c.

2877{
2878 struct dahdi_pvt *pvt;
2879 int polarity;
2880
2881 pvt = fxo_pvt(chan);
2882 if (!pvt) {
2883 return -1;
2884 }
2885
2886 if (!strcasecmp(value, "idle")) {
2888 } else if (!strcasecmp(value, "reverse")) {
2890 } else {
2891 polarity = atoi(value);
2892 }
2893
2895 ast_log(LOG_WARNING, "Invalid polarity: '%s'\n", value);
2896 return -1;
2897 }
2898
2900 return 0;
2901}

References ast_log, fxo_pvt(), LOG_WARNING, my_set_polarity(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, and value.

◆ process_dahdi()

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

Definition at line 18459 of file chan_dahdi.c.

18460{
18461 struct dahdi_pvt *tmp;
18462 int y;
18463 struct ast_variable *dahdichan = NULL;
18464
18465 /* Re-parse any cadences from beginning, rather than appending until we run out of room */
18467
18468 for (; v; v = v->next) {
18470 continue;
18471
18472 /* Create the interface list */
18473 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
18475 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
18476 continue;
18477 }
18478 if (build_channels(confp, v->value, reload, v->lineno)) {
18479 if (confp->ignore_failed_channels) {
18480 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
18481 continue;
18482 } else {
18483 return -1;
18484 }
18485 }
18486 ast_debug(1, "Channel '%s' configured.\n", v->value);
18487 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
18489 } else if (!strcasecmp(v->name, "buffers")) {
18490 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
18491 ast_log(LOG_WARNING, "Using default buffer policy.\n");
18492 confp->chan.buf_no = numbufs;
18493 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
18494 }
18495 } else if (!strcasecmp(v->name, "faxbuffers")) {
18496 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
18497 confp->chan.usefaxbuffers = 1;
18498 }
18499 } else if (!strcasecmp(v->name, "dahdichan")) {
18500 /* Only process the last dahdichan value. */
18501 dahdichan = v;
18502 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
18504 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
18506 } else if (!strcasecmp(v->name, "dring1context")) {
18508 } else if (!strcasecmp(v->name, "dring2context")) {
18510 } else if (!strcasecmp(v->name, "dring3context")) {
18512 } else if (!strcasecmp(v->name, "dring1range")) {
18513 confp->chan.drings.ringnum[0].range = atoi(v->value);
18514 } else if (!strcasecmp(v->name, "dring2range")) {
18515 confp->chan.drings.ringnum[1].range = atoi(v->value);
18516 } else if (!strcasecmp(v->name, "dring3range")) {
18517 confp->chan.drings.ringnum[2].range = atoi(v->value);
18518 } else if (!strcasecmp(v->name, "dring1")) {
18519 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]);
18520 } else if (!strcasecmp(v->name, "dring2")) {
18521 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]);
18522 } else if (!strcasecmp(v->name, "dring3")) {
18523 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]);
18524 } else if (!strcasecmp(v->name, "usecallerid")) {
18525 confp->chan.use_callerid = ast_true(v->value);
18526 } else if (!strcasecmp(v->name, "cidsignalling")) {
18527 if (!strcasecmp(v->value, "bell"))
18529 else if (!strcasecmp(v->value, "v23"))
18531 else if (!strcasecmp(v->value, "dtmf"))
18533 else if (!strcasecmp(v->value, "smdi"))
18535 else if (!strcasecmp(v->value, "v23_jp"))
18537 else if (ast_true(v->value))
18539 } else if (!strcasecmp(v->name, "cidstart")) {
18540 if (!strcasecmp(v->value, "ring"))
18541 confp->chan.cid_start = CID_START_RING;
18542 else if (!strcasecmp(v->value, "polarity_in"))
18544 else if (!strcasecmp(v->value, "polarity"))
18546 else if (!strcasecmp(v->value, "dtmf"))
18548 else if (ast_true(v->value))
18549 confp->chan.cid_start = CID_START_RING;
18550 } else if (!strcasecmp(v->name, "threewaycalling")) {
18551 confp->chan.threewaycalling = ast_true(v->value);
18552 } else if (!strcasecmp(v->name, "threewaysilenthold")) {
18554 } else if (!strcasecmp(v->name, "cancallforward")) {
18555 confp->chan.cancallforward = ast_true(v->value);
18556 } else if (!strcasecmp(v->name, "relaxdtmf")) {
18557 if (ast_true(v->value))
18559 else
18560 confp->chan.dtmfrelax = 0;
18561 } else if (!strcasecmp(v->name, "mailbox")) {
18562 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
18563 } else if (!strcasecmp(v->name, "description")) {
18564 ast_copy_string(confp->chan.description, v->value, sizeof(confp->chan.description));
18565 } else if (!strcasecmp(v->name, "hasvoicemail")) {
18566 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
18567 /*
18568 * hasvoicemail is a users.conf legacy voicemail enable method.
18569 * hasvoicemail is only going to work for app_voicemail mailboxes.
18570 */
18571 if (strchr(cat, '@')) {
18572 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
18573 } else {
18574 snprintf(confp->chan.mailbox, sizeof(confp->chan.mailbox),
18575 "%s@default", cat);
18576 }
18577 }
18578 } else if (!strcasecmp(v->name, "adsi")) {
18579 confp->chan.adsi = ast_true(v->value);
18580 } else if (!strcasecmp(v->name, "usesmdi")) {
18581 confp->chan.use_smdi = ast_true(v->value);
18582 } else if (!strcasecmp(v->name, "smdiport")) {
18583 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
18584 } else if (!strcasecmp(v->name, "transfer")) {
18585 confp->chan.transfer = ast_true(v->value);
18586 } else if (!strcasecmp(v->name, "canpark")) {
18587 confp->chan.canpark = ast_true(v->value);
18588 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
18589 confp->chan.echocanbridged = ast_true(v->value);
18590 } else if (!strcasecmp(v->name, "busydetect")) {
18591 confp->chan.busydetect = ast_true(v->value);
18592 } else if (!strcasecmp(v->name, "busycount")) {
18593 confp->chan.busycount = atoi(v->value);
18594 } else if (!strcasecmp(v->name, "busypattern")) {
18596 } else if (!strcasecmp(v->name, "calledsubscriberheld")) {
18598 } else if (!strcasecmp(v->name, "callprogress")) {
18599 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
18600 if (ast_true(v->value))
18602 } else if (!strcasecmp(v->name, "waitfordialtone")) {
18603 confp->chan.waitfordialtone = atoi(v->value);
18604 } else if (!strcasecmp(v->name, "dialtone_detect")) {
18605 if (!strcasecmp(v->value, "always")) {
18606 confp->chan.dialtone_detect = -1;
18607 } else if (ast_true(v->value)) {
18609 } else if (ast_false(v->value)) {
18610 confp->chan.dialtone_detect = 0;
18611 } else {
18612 confp->chan.dialtone_detect = ast_strlen_zero(v->value) ? 0 : (8 * atoi(v->value)) / READ_SIZE;
18613 }
18614 } else if (!strcasecmp(v->name, "faxdetect")) {
18615 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
18616 if (!strcasecmp(v->value, "incoming")) {
18618 } else if (!strcasecmp(v->value, "outgoing")) {
18620 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
18622 } else if (!strcasecmp(v->name, "faxdetect_timeout")) {
18623 if (sscanf(v->value, "%30u", &confp->chan.faxdetect_timeout) != 1) {
18624 confp->chan.faxdetect_timeout = 0;
18625 }
18626 } else if (!strcasecmp(v->name, "firstdigit_timeout")) {
18627 if (sscanf(v->value, "%30d", &confp->chan.firstdigit_timeout) != 1
18628 || confp->chan.firstdigit_timeout <= 0) {
18630 }
18631 } else if (!strcasecmp(v->name, "interdigit_timeout")) {
18632 if (sscanf(v->value, "%30d", &confp->chan.interdigit_timeout) != 1
18633 || confp->chan.interdigit_timeout <= 0) {
18635 }
18636 } else if (!strcasecmp(v->name, "matchdigit_timeout")) {
18637 if (sscanf(v->value, "%30d", &confp->chan.matchdigit_timeout) != 1
18638 || confp->chan.matchdigit_timeout <= 0) {
18640 }
18641 } else if (!strcasecmp(v->name, "echocancel")) {
18642 process_echocancel(confp, v->value, v->lineno);
18643 } else if (!strcasecmp(v->name, "echotraining")) {
18644 if (sscanf(v->value, "%30d", &y) == 1) {
18645 if ((y < 10) || (y > 4000)) {
18646 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
18647 } else {
18648 confp->chan.echotraining = y;
18649 }
18650 } else if (ast_true(v->value)) {
18651 confp->chan.echotraining = 400;
18652 } else
18653 confp->chan.echotraining = 0;
18654 } else if (!strcasecmp(v->name, "hidecallerid")) {
18655 confp->chan.hidecallerid = ast_true(v->value);
18656 } else if (!strcasecmp(v->name, "hidecalleridname")) {
18657 confp->chan.hidecalleridname = ast_true(v->value);
18658 } else if (!strcasecmp(v->name, "pulsedial")) {
18659 confp->chan.pulse = ast_true(v->value);
18660 } else if (!strcasecmp(v->name, "callreturn")) {
18661 confp->chan.callreturn = ast_true(v->value);
18662 } else if (!strcasecmp(v->name, "callwaiting")) {
18663 confp->chan.callwaiting = ast_true(v->value);
18664 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
18666 } else if (!strcasecmp(v->name, "context")) {
18667 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
18668 } else if (!strcasecmp(v->name, "language")) {
18669 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
18670 } else if (!strcasecmp(v->name, "progzone")) {
18671 ast_copy_string(progzone, v->value, sizeof(progzone));
18672 } else if (!strcasecmp(v->name, "mohinterpret")
18673 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
18674 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
18675 } else if (!strcasecmp(v->name, "mohsuggest")) {
18676 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
18677 } else if (!strcasecmp(v->name, "parkinglot")) {
18678 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
18679 } else if (!strcasecmp(v->name, "stripmsd")) {
18680 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
18681 confp->chan.stripmsd = atoi(v->value);
18682 } else if (!strcasecmp(v->name, "jitterbuffers")) {
18683 numbufs = atoi(v->value);
18684 } else if (!strcasecmp(v->name, "group")) {
18685 confp->chan.group = ast_get_group(v->value);
18686 } else if (!strcasecmp(v->name, "callgroup")) {
18687 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18688 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a call group\n");
18689 }
18690 if (!strcasecmp(v->value, "none"))
18691 confp->chan.callgroup = 0;
18692 else
18693 confp->chan.callgroup = ast_get_group(v->value);
18694 } else if (!strcasecmp(v->name, "pickupgroup")) {
18695 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18696 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a pickup group\n");
18697 }
18698 if (!strcasecmp(v->value, "none"))
18699 confp->chan.pickupgroup = 0;
18700 else
18701 confp->chan.pickupgroup = ast_get_group(v->value);
18702 } else if (!strcasecmp(v->name, "namedcallgroup")) {
18703 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18704 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a named call group\n");
18705 }
18707 } else if (!strcasecmp(v->name, "namedpickupgroup")) {
18708 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18709 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a named pickup group\n");
18710 }
18712 } else if (!strcasecmp(v->name, "setvar")) {
18713 if (v->value) {
18714 char *varval = NULL;
18715 struct ast_variable *tmpvar;
18716 char varname[strlen(v->value) + 1];
18717 strcpy(varname, v->value); /* safe */
18718 if ((varval = strchr(varname, '='))) {
18719 *varval++ = '\0';
18720 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
18721 if (ast_variable_list_replace(&confp->chan.vars, tmpvar)) {
18722 tmpvar->next = confp->chan.vars;
18723 confp->chan.vars = tmpvar;
18724 }
18725 }
18726 }
18727 }
18728 } else if (!strcasecmp(v->name, "immediate")) {
18729 confp->chan.immediate = ast_true(v->value);
18730 } else if (!strcasecmp(v->name, "immediatering")) {
18731 confp->chan.immediatering = ast_true(v->value);
18732 } else if (!strcasecmp(v->name, "transfertobusy")) {
18733 confp->chan.transfertobusy = ast_true(v->value);
18734 } else if (!strcasecmp(v->name, "dialmode")) {
18735 if (!strcasecmp(v->value, "pulse")) {
18737 } else if (!strcasecmp(v->value, "dtmf") || !strcasecmp(v->value, "tone")) {
18739 } else if (!strcasecmp(v->value, "none")) {
18741 } else {
18743 }
18744 } else if (!strcasecmp(v->name, "mwimonitor")) {
18745 confp->chan.mwimonitor_neon = 0;
18746 confp->chan.mwimonitor_fsk = 0;
18747 confp->chan.mwimonitor_rpas = 0;
18748 if (strcasestr(v->value, "fsk")) {
18749 confp->chan.mwimonitor_fsk = 1;
18750 }
18751 if (strcasestr(v->value, "rpas")) {
18752 confp->chan.mwimonitor_rpas = 1;
18753 }
18754 if (strcasestr(v->value, "neon")) {
18755 confp->chan.mwimonitor_neon = 1;
18756 }
18757 /* If set to true or yes, assume that simple fsk is desired */
18758 if (ast_true(v->value)) {
18759 confp->chan.mwimonitor_fsk = 1;
18760 }
18761 } else if (!strcasecmp(v->name, "hwrxgain")) {
18762 confp->chan.hwrxgain_enabled = 0;
18763 if (strcasecmp(v->value, "disabled")) {
18764 if (sscanf(v->value, "%30f", &confp->chan.hwrxgain) == 1) {
18765 confp->chan.hwrxgain_enabled = 1;
18766 } else {
18767 ast_log(LOG_WARNING, "Invalid hwrxgain: %s at line %d.\n", v->value, v->lineno);
18768 }
18769 }
18770 } else if (!strcasecmp(v->name, "hwtxgain")) {
18771 confp->chan.hwtxgain_enabled = 0;
18772 if (strcasecmp(v->value, "disabled")) {
18773 if (sscanf(v->value, "%30f", &confp->chan.hwtxgain) == 1) {
18774 confp->chan.hwtxgain_enabled = 1;
18775 } else {
18776 ast_log(LOG_WARNING, "Invalid hwtxgain: %s at line %d.\n", v->value, v->lineno);
18777 }
18778 }
18779 } else if (!strcasecmp(v->name, "cid_rxgain")) {
18780 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
18781 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
18782 }
18783 } else if (!strcasecmp(v->name, "rxgain")) {
18784 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
18785 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
18786 }
18787 } else if (!strcasecmp(v->name, "txgain")) {
18788 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
18789 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
18790 }
18791 } else if (!strcasecmp(v->name, "txdrc")) {
18792 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
18793 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
18794 }
18795 } else if (!strcasecmp(v->name, "rxdrc")) {
18796 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
18797 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
18798 }
18799 } else if (!strcasecmp(v->name, "tonezone")) {
18800 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
18801 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
18802 }
18803 } else if (!strcasecmp(v->name, "callerid")) {
18804 if (!strcasecmp(v->value, "asreceived")) {
18805 confp->chan.cid_num[0] = '\0';
18806 confp->chan.cid_name[0] = '\0';
18807 } else {
18808 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
18809 }
18810 } else if (!strcasecmp(v->name, "fullname")) {
18811 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
18812 } else if (!strcasecmp(v->name, "cid_number")) {
18813 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
18814 } else if (!strcasecmp(v->name, "cid_tag")) {
18815 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
18816 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
18817 confp->chan.dahditrcallerid = ast_true(v->value);
18818 } else if (!strcasecmp(v->name, "restrictcid")) {
18819 confp->chan.restrictcid = ast_true(v->value);
18820 } else if (!strcasecmp(v->name, "usecallingpres")) {
18821 confp->chan.use_callingpres = ast_true(v->value);
18822 } else if (!strcasecmp(v->name, "accountcode")) {
18823 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
18824 } else if (!strcasecmp(v->name, "amaflags")) {
18826 if (y < 0)
18827 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
18828 else
18829 confp->chan.amaflags = y;
18830 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
18831 confp->chan.polarityonanswerdelay = atoi(v->value);
18832 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
18834 } else if (!strcasecmp(v->name, "ani_info_digits")) {
18835 confp->chan.ani_info_digits = atoi(v->value);
18836 } else if (!strcasecmp(v->name, "ani_wink_time")) {
18837 confp->chan.ani_wink_time = atoi(v->value);
18838 } else if (!strcasecmp(v->name, "ani_timeout")) {
18839 confp->chan.ani_timeout = atoi(v->value);
18840 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
18842 } else if (!strcasecmp(v->name, "autoreoriginate")) {
18843 confp->chan.reoriginate = ast_true(v->value);
18844 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
18845 confp->chan.sendcalleridafter = atoi(v->value);
18846 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
18848 } else if (ast_cc_is_config_param(v->name)) {
18849 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
18850 } else if (!strcasecmp(v->name, "mwisendtype")) {
18851#ifndef HAVE_DAHDI_LINEREVERSE_VMWI /* backward compatibility for older dahdi VMWI implementation */
18852 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
18853 mwisend_rpas = 1;
18854 } else {
18855 mwisend_rpas = 0;
18856 }
18857#else
18858 /* Default is fsk, to turn it off you must specify nofsk */
18859 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
18860 if (strcasestr(v->value, "nofsk")) { /* NoFSK */
18861 confp->chan.mwisend_fsk = 0;
18862 } else { /* Default FSK */
18863 confp->chan.mwisend_fsk = 1;
18864 }
18865 if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */
18866 confp->chan.mwisend_rpas = 1;
18867 } else {
18868 confp->chan.mwisend_rpas = 0;
18869 }
18870 if (strcasestr(v->value, "lrev")) { /* Line Reversal */
18871 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
18872 }
18873 if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */
18874 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
18875 }
18876 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ) { /* 90V DC pulses */
18877 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
18878 }
18879#endif
18880 } else if (reload != 1) {
18881 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
18882 int orig_radio = confp->chan.radio;
18883 int orig_outsigmod = confp->chan.outsigmod;
18884 int orig_auto = confp->is_sig_auto;
18885
18886 confp->chan.radio = 0;
18887 confp->chan.outsigmod = -1;
18888 confp->is_sig_auto = 0;
18889 if (!strcasecmp(v->value, "em")) {
18890 confp->chan.sig = SIG_EM;
18891 } else if (!strcasecmp(v->value, "em_e1")) {
18892 confp->chan.sig = SIG_EM_E1;
18893 } else if (!strcasecmp(v->value, "em_w")) {
18894 confp->chan.sig = SIG_EMWINK;
18895 } else if (!strcasecmp(v->value, "fxs_ls")) {
18896 confp->chan.sig = SIG_FXSLS;
18897 } else if (!strcasecmp(v->value, "fxs_gs")) {
18898 confp->chan.sig = SIG_FXSGS;
18899 } else if (!strcasecmp(v->value, "fxs_ks")) {
18900 confp->chan.sig = SIG_FXSKS;
18901 } else if (!strcasecmp(v->value, "fxo_ls")) {
18902 confp->chan.sig = SIG_FXOLS;
18903 } else if (!strcasecmp(v->value, "fxo_gs")) {
18904 confp->chan.sig = SIG_FXOGS;
18905 } else if (!strcasecmp(v->value, "fxo_ks")) {
18906 confp->chan.sig = SIG_FXOKS;
18907 } else if (!strcasecmp(v->value, "fxs_rx")) {
18908 confp->chan.sig = SIG_FXSKS;
18909 confp->chan.radio = 1;
18910 } else if (!strcasecmp(v->value, "fxo_rx")) {
18911 confp->chan.sig = SIG_FXOLS;
18912 confp->chan.radio = 1;
18913 } else if (!strcasecmp(v->value, "fxs_tx")) {
18914 confp->chan.sig = SIG_FXSLS;
18915 confp->chan.radio = 1;
18916 } else if (!strcasecmp(v->value, "fxo_tx")) {
18917 confp->chan.sig = SIG_FXOGS;
18918 confp->chan.radio = 1;
18919 } else if (!strcasecmp(v->value, "em_rx")) {
18920 confp->chan.sig = SIG_EM;
18921 confp->chan.radio = 1;
18922 } else if (!strcasecmp(v->value, "em_tx")) {
18923 confp->chan.sig = SIG_EM;
18924 confp->chan.radio = 1;
18925 } else if (!strcasecmp(v->value, "em_rxtx")) {
18926 confp->chan.sig = SIG_EM;
18927 confp->chan.radio = 2;
18928 } else if (!strcasecmp(v->value, "em_txrx")) {
18929 confp->chan.sig = SIG_EM;
18930 confp->chan.radio = 2;
18931 } else if (!strcasecmp(v->value, "sf")) {
18932 confp->chan.sig = SIG_SF;
18933 } else if (!strcasecmp(v->value, "sf_w")) {
18934 confp->chan.sig = SIG_SFWINK;
18935 } else if (!strcasecmp(v->value, "sf_featd")) {
18936 confp->chan.sig = SIG_FEATD;
18937 } else if (!strcasecmp(v->value, "sf_featdmf")) {
18938 confp->chan.sig = SIG_FEATDMF;
18939 } else if (!strcasecmp(v->value, "sf_featb")) {
18940 confp->chan.sig = SIG_SF_FEATB;
18941 } else if (!strcasecmp(v->value, "sf")) {
18942 confp->chan.sig = SIG_SF;
18943 } else if (!strcasecmp(v->value, "sf_rx")) {
18944 confp->chan.sig = SIG_SF;
18945 confp->chan.radio = 1;
18946 } else if (!strcasecmp(v->value, "sf_tx")) {
18947 confp->chan.sig = SIG_SF;
18948 confp->chan.radio = 1;
18949 } else if (!strcasecmp(v->value, "sf_rxtx")) {
18950 confp->chan.sig = SIG_SF;
18951 confp->chan.radio = 2;
18952 } else if (!strcasecmp(v->value, "sf_txrx")) {
18953 confp->chan.sig = SIG_SF;
18954 confp->chan.radio = 2;
18955 } else if (!strcasecmp(v->value, "featd")) {
18956 confp->chan.sig = SIG_FEATD;
18957 } else if (!strcasecmp(v->value, "featdmf")) {
18958 confp->chan.sig = SIG_FEATDMF;
18959 } else if (!strcasecmp(v->value, "featdmf_ta")) {
18960 confp->chan.sig = SIG_FEATDMF_TA;
18961 } else if (!strcasecmp(v->value, "e911")) {
18962 confp->chan.sig = SIG_E911;
18963 } else if (!strcasecmp(v->value, "fgccama")) {
18964 confp->chan.sig = SIG_FGC_CAMA;
18965 } else if (!strcasecmp(v->value, "fgccamamf")) {
18966 confp->chan.sig = SIG_FGC_CAMAMF;
18967 } else if (!strcasecmp(v->value, "featb")) {
18968 confp->chan.sig = SIG_FEATB;
18969#ifdef HAVE_PRI
18970 } else if (!strcasecmp(v->value, "pri_net")) {
18971 confp->chan.sig = SIG_PRI;
18972 confp->pri.pri.nodetype = PRI_NETWORK;
18973 } else if (!strcasecmp(v->value, "pri_cpe")) {
18974 confp->chan.sig = SIG_PRI;
18975 confp->pri.pri.nodetype = PRI_CPE;
18976 } else if (!strcasecmp(v->value, "bri_cpe")) {
18977 confp->chan.sig = SIG_BRI;
18978 confp->pri.pri.nodetype = PRI_CPE;
18979 } else if (!strcasecmp(v->value, "bri_net")) {
18980 confp->chan.sig = SIG_BRI;
18981 confp->pri.pri.nodetype = PRI_NETWORK;
18982 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
18983 confp->chan.sig = SIG_BRI_PTMP;
18984 confp->pri.pri.nodetype = PRI_CPE;
18985 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
18986#if defined(HAVE_PRI_CALL_HOLD)
18987 confp->chan.sig = SIG_BRI_PTMP;
18988 confp->pri.pri.nodetype = PRI_NETWORK;
18989#else
18990 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
18991#endif /* !defined(HAVE_PRI_CALL_HOLD) */
18992#endif
18993#if defined(HAVE_SS7)
18994 } else if (!strcasecmp(v->value, "ss7")) {
18995 confp->chan.sig = SIG_SS7;
18996#endif /* defined(HAVE_SS7) */
18997#ifdef HAVE_OPENR2
18998 } else if (!strcasecmp(v->value, "mfcr2")) {
18999 confp->chan.sig = SIG_MFCR2;
19000#endif
19001 } else if (!strcasecmp(v->value, "auto")) {
19002 confp->is_sig_auto = 1;
19003 } else {
19004 confp->chan.outsigmod = orig_outsigmod;
19005 confp->chan.radio = orig_radio;
19006 confp->is_sig_auto = orig_auto;
19007 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
19008 }
19009 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
19010 if (!strcasecmp(v->value, "em")) {
19011 confp->chan.outsigmod = SIG_EM;
19012 } else if (!strcasecmp(v->value, "em_e1")) {
19013 confp->chan.outsigmod = SIG_EM_E1;
19014 } else if (!strcasecmp(v->value, "em_w")) {
19015 confp->chan.outsigmod = SIG_EMWINK;
19016 } else if (!strcasecmp(v->value, "sf")) {
19017 confp->chan.outsigmod = SIG_SF;
19018 } else if (!strcasecmp(v->value, "sf_w")) {
19019 confp->chan.outsigmod = SIG_SFWINK;
19020 } else if (!strcasecmp(v->value, "sf_featd")) {
19021 confp->chan.outsigmod = SIG_FEATD;
19022 } else if (!strcasecmp(v->value, "sf_featdmf")) {
19023 confp->chan.outsigmod = SIG_FEATDMF;
19024 } else if (!strcasecmp(v->value, "sf_featb")) {
19025 confp->chan.outsigmod = SIG_SF_FEATB;
19026 } else if (!strcasecmp(v->value, "sf")) {
19027 confp->chan.outsigmod = SIG_SF;
19028 } else if (!strcasecmp(v->value, "featd")) {
19029 confp->chan.outsigmod = SIG_FEATD;
19030 } else if (!strcasecmp(v->value, "featdmf")) {
19031 confp->chan.outsigmod = SIG_FEATDMF;
19032 } else if (!strcasecmp(v->value, "featdmf_ta")) {
19033 confp->chan.outsigmod = SIG_FEATDMF_TA;
19034 } else if (!strcasecmp(v->value, "e911")) {
19035 confp->chan.outsigmod = SIG_E911;
19036 } else if (!strcasecmp(v->value, "fgccama")) {
19037 confp->chan.outsigmod = SIG_FGC_CAMA;
19038 } else if (!strcasecmp(v->value, "fgccamamf")) {
19039 confp->chan.outsigmod = SIG_FGC_CAMAMF;
19040 } else if (!strcasecmp(v->value, "featb")) {
19041 confp->chan.outsigmod = SIG_FEATB;
19042 } else {
19043 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
19044 }
19045#ifdef HAVE_PRI
19046 } else if (!strcasecmp(v->name, "pridialplan")) {
19047 if (!strcasecmp(v->value, "national")) {
19048 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
19049 } else if (!strcasecmp(v->value, "unknown")) {
19050 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
19051 } else if (!strcasecmp(v->value, "private")) {
19052 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
19053 } else if (!strcasecmp(v->value, "international")) {
19054 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
19055 } else if (!strcasecmp(v->value, "local")) {
19056 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
19057 } else if (!strcasecmp(v->value, "dynamic")) {
19058 confp->pri.pri.dialplan = -1;
19059 } else if (!strcasecmp(v->value, "redundant")) {
19060 confp->pri.pri.dialplan = -2;
19061 } else {
19062 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
19063 }
19064 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
19065 if (!strcasecmp(v->value, "national")) {
19066 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
19067 } else if (!strcasecmp(v->value, "unknown")) {
19068 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
19069 } else if (!strcasecmp(v->value, "private")) {
19070 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
19071 } else if (!strcasecmp(v->value, "international")) {
19072 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
19073 } else if (!strcasecmp(v->value, "local")) {
19074 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
19075 } else if (!strcasecmp(v->value, "from_channel")) {
19076 confp->pri.pri.localdialplan = 0;
19077 } else if (!strcasecmp(v->value, "dynamic")) {
19078 confp->pri.pri.localdialplan = -1;
19079 } else if (!strcasecmp(v->value, "redundant")) {
19080 confp->pri.pri.localdialplan = -2;
19081 } else {
19082 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
19083 }
19084 } else if (!strcasecmp(v->name, "pricpndialplan")) {
19085 if (!strcasecmp(v->value, "national")) {
19086 confp->pri.pri.cpndialplan = PRI_NATIONAL_ISDN + 1;
19087 } else if (!strcasecmp(v->value, "unknown")) {
19088 confp->pri.pri.cpndialplan = PRI_UNKNOWN + 1;
19089 } else if (!strcasecmp(v->value, "private")) {
19090 confp->pri.pri.cpndialplan = PRI_PRIVATE + 1;
19091 } else if (!strcasecmp(v->value, "international")) {
19092 confp->pri.pri.cpndialplan = PRI_INTERNATIONAL_ISDN + 1;
19093 } else if (!strcasecmp(v->value, "local")) {
19094 confp->pri.pri.cpndialplan = PRI_LOCAL_ISDN + 1;
19095 } else if (!strcasecmp(v->value, "from_channel")) {
19096 confp->pri.pri.cpndialplan = 0;
19097 } else if (!strcasecmp(v->value, "dynamic")) {
19098 confp->pri.pri.cpndialplan = -1;
19099 } else if (!strcasecmp(v->value, "redundant")) {
19100 confp->pri.pri.cpndialplan = -2;
19101 } else {
19102 ast_log(LOG_WARNING, "Unknown PRI cpndialplan '%s' at line %d.\n", v->value, v->lineno);
19103 }
19104 } else if (!strcasecmp(v->name, "switchtype")) {
19105 if (!strcasecmp(v->value, "national"))
19106 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
19107 else if (!strcasecmp(v->value, "ni1"))
19108 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
19109 else if (!strcasecmp(v->value, "dms100"))
19110 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
19111 else if (!strcasecmp(v->value, "4ess"))
19112 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
19113 else if (!strcasecmp(v->value, "5ess"))
19114 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
19115 else if (!strcasecmp(v->value, "euroisdn"))
19116 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
19117 else if (!strcasecmp(v->value, "qsig"))
19118 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
19119 else {
19120 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
19121 return -1;
19122 }
19123 } else if (!strcasecmp(v->name, "msn")) {
19124 ast_copy_string(confp->pri.pri.msn_list, v->value,
19125 sizeof(confp->pri.pri.msn_list));
19126 } else if (!strcasecmp(v->name, "nsf")) {
19127 if (!strcasecmp(v->value, "sdn"))
19128 confp->pri.pri.nsf = PRI_NSF_SDN;
19129 else if (!strcasecmp(v->value, "megacom"))
19130 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
19131 else if (!strcasecmp(v->value, "tollfreemegacom"))
19132 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
19133 else if (!strcasecmp(v->value, "accunet"))
19134 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
19135 else if (!strcasecmp(v->value, "none"))
19136 confp->pri.pri.nsf = PRI_NSF_NONE;
19137 else {
19138 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
19139 confp->pri.pri.nsf = PRI_NSF_NONE;
19140 }
19141 } else if (!strcasecmp(v->name, "priindication")) {
19142 if (!strcasecmp(v->value, "outofband"))
19143 confp->chan.priindication_oob = 1;
19144 else if (!strcasecmp(v->value, "inband"))
19145 confp->chan.priindication_oob = 0;
19146 else
19147 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
19148 v->value, v->lineno);
19149 } else if (!strcasecmp(v->name, "priexclusive")) {
19150 confp->chan.priexclusive = ast_true(v->value);
19151 } else if (!strcasecmp(v->name, "internationalprefix")) {
19152 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
19153 } else if (!strcasecmp(v->name, "nationalprefix")) {
19154 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
19155 } else if (!strcasecmp(v->name, "localprefix")) {
19156 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
19157 } else if (!strcasecmp(v->name, "privateprefix")) {
19158 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
19159 } else if (!strcasecmp(v->name, "unknownprefix")) {
19160 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
19161 } else if (!strcasecmp(v->name, "resetinterval")) {
19162 if (!strcasecmp(v->value, "never"))
19163 confp->pri.pri.resetinterval = -1;
19164 else if (atoi(v->value) >= 60)
19165 confp->pri.pri.resetinterval = atoi(v->value);
19166 else
19167 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
19168 v->value, v->lineno);
19169 } else if (!strcasecmp(v->name, "force_restart_unavailable_chans")) {
19170 confp->pri.pri.force_restart_unavailable_chans = ast_true(v->value);
19171 } else if (!strcasecmp(v->name, "minunused")) {
19172 confp->pri.pri.minunused = atoi(v->value);
19173 } else if (!strcasecmp(v->name, "minidle")) {
19174 confp->pri.pri.minidle = atoi(v->value);
19175 } else if (!strcasecmp(v->name, "idleext")) {
19176 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
19177 } else if (!strcasecmp(v->name, "idledial")) {
19178 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
19179 } else if (!strcasecmp(v->name, "overlapdial")) {
19180 if (ast_true(v->value)) {
19181 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
19182 } else if (!strcasecmp(v->value, "incoming")) {
19183 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
19184 } else if (!strcasecmp(v->value, "outgoing")) {
19185 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
19186 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
19187 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
19188 } else {
19189 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
19190 }
19191#ifdef HAVE_PRI_PROG_W_CAUSE
19192 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
19193 if (!strcasecmp(v->value, "logical")) {
19194 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
19195 } else if (!strcasecmp(v->value, "physical")) {
19196 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
19197 } else {
19198 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
19199 }
19200#endif
19201 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
19202 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
19203#if defined(HAVE_PRI_SERVICE_MESSAGES)
19204 } else if (!strcasecmp(v->name, "service_message_support")) {
19205 /* assuming switchtype for this channel group has been configured already */
19206 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
19207 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
19208 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
19209 confp->pri.pri.enable_service_message_support = 1;
19210 } else {
19211 confp->pri.pri.enable_service_message_support = 0;
19212 }
19213#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
19214#ifdef HAVE_PRI_INBANDDISCONNECT
19215 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
19216 confp->pri.pri.inbanddisconnect = ast_true(v->value);
19217#endif
19218 } else if (!strcasecmp(v->name, "pritimer")) {
19219#ifdef PRI_GETSET_TIMERS
19220 char tmp[20];
19221 char *timerc;
19222 char *c;
19223 int timer;
19224 int timeridx;
19225
19226 ast_copy_string(tmp, v->value, sizeof(tmp));
19227 c = tmp;
19228 timerc = strsep(&c, ",");
19229 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
19230 timeridx = pri_timer2idx(timerc);
19231 timer = atoi(c);
19232 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
19234 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
19235 v->lineno);
19236 } else if (!timer) {
19238 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
19239 c, timerc, v->lineno);
19240 } else {
19241 confp->pri.pri.pritimers[timeridx] = timer;
19242 }
19243 } else {
19245 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
19246 v->value, v->lineno);
19247 }
19248#endif /* PRI_GETSET_TIMERS */
19249 } else if (!strcasecmp(v->name, "facilityenable")) {
19250 confp->pri.pri.facilityenable = ast_true(v->value);
19251#if defined(HAVE_PRI_AOC_EVENTS)
19252 } else if (!strcasecmp(v->name, "aoc_enable")) {
19253 confp->pri.pri.aoc_passthrough_flag = 0;
19254 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
19255 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
19256 }
19257 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
19258 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
19259 }
19260 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
19261 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
19262 }
19263 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
19264 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
19265#endif /* defined(HAVE_PRI_AOC_EVENTS) */
19266#if defined(HAVE_PRI_CALL_HOLD)
19267 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
19268 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
19269#endif /* defined(HAVE_PRI_CALL_HOLD) */
19270 } else if (!strcasecmp(v->name, "moh_signaling")
19271 || !strcasecmp(v->name, "moh_signalling")) {
19272 if (!strcasecmp(v->value, "moh")) {
19273 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
19274 } else if (!strcasecmp(v->value, "notify")) {
19275 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_NOTIFY;
19276#if defined(HAVE_PRI_CALL_HOLD)
19277 } else if (!strcasecmp(v->value, "hold")) {
19278 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_HOLD;
19279#endif /* defined(HAVE_PRI_CALL_HOLD) */
19280 } else {
19281 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
19282 }
19283#if defined(HAVE_PRI_CCSS)
19284 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
19285 if (!strcasecmp(v->value, "global")) {
19286 confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
19287 } else if (!strcasecmp(v->value, "specific")) {
19288 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
19289 } else {
19290 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
19291 }
19292 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
19293 if (!strcasecmp(v->value, "release")) {
19294 confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
19295 } else if (!strcasecmp(v->value, "retain")) {
19296 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
19297 } else if (!strcasecmp(v->value, "do_not_care")) {
19298 confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
19299 } else {
19300 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
19301 }
19302 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
19303 if (!strcasecmp(v->value, "release")) {
19304 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
19305 } else if (!strcasecmp(v->value, "retain")) {
19306 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
19307 } else {
19308 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
19309 }
19310#endif /* defined(HAVE_PRI_CCSS) */
19311#if defined(HAVE_PRI_CALL_WAITING)
19312 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
19313 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
19314 if (confp->pri.pri.max_call_waiting_calls < 0) {
19315 /* Negative values are not allowed. */
19316 confp->pri.pri.max_call_waiting_calls = 0;
19317 }
19318 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
19319 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
19320#endif /* defined(HAVE_PRI_CALL_WAITING) */
19321#if defined(HAVE_PRI_MWI)
19322 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
19323 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
19324 sizeof(confp->pri.pri.mwi_mailboxes));
19325 } else if (!strcasecmp(v->name, "mwi_vm_boxes")) {
19326 ast_copy_string(confp->pri.pri.mwi_vm_boxes, v->value,
19327 sizeof(confp->pri.pri.mwi_vm_boxes));
19328 } else if (!strcasecmp(v->name, "mwi_vm_numbers")) {
19329 ast_copy_string(confp->pri.pri.mwi_vm_numbers, v->value,
19330 sizeof(confp->pri.pri.mwi_vm_numbers));
19331#endif /* defined(HAVE_PRI_MWI) */
19332 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
19333 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
19334 } else if (!strcasecmp(v->name, "inband_on_setup_ack")) {
19335 confp->pri.pri.inband_on_setup_ack = ast_true(v->value);
19336 } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
19337 confp->pri.pri.inband_on_proceeding = ast_true(v->value);
19338#if defined(HAVE_PRI_DISPLAY_TEXT)
19339 } else if (!strcasecmp(v->name, "display_send")) {
19340 confp->pri.pri.display_flags_send = dahdi_display_text_option(v->value);
19341 } else if (!strcasecmp(v->name, "display_receive")) {
19342 confp->pri.pri.display_flags_receive = dahdi_display_text_option(v->value);
19343#endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
19344#if defined(HAVE_PRI_MCID)
19345 } else if (!strcasecmp(v->name, "mcid_send")) {
19346 confp->pri.pri.mcid_send = ast_true(v->value);
19347#endif /* defined(HAVE_PRI_MCID) */
19348#if defined(HAVE_PRI_DATETIME_SEND)
19349 } else if (!strcasecmp(v->name, "datetime_send")) {
19350 confp->pri.pri.datetime_send = dahdi_datetime_send_option(v->value);
19351#endif /* defined(HAVE_PRI_DATETIME_SEND) */
19352 } else if (!strcasecmp(v->name, "layer1_presence")) {
19353 if (!strcasecmp(v->value, "required")) {
19354 confp->pri.pri.layer1_ignored = 0;
19355 } else if (!strcasecmp(v->value, "ignore")) {
19356 confp->pri.pri.layer1_ignored = 1;
19357 } else {
19358 /* Default */
19359 confp->pri.pri.layer1_ignored = 0;
19360 }
19361#if defined(HAVE_PRI_L2_PERSISTENCE)
19362 } else if (!strcasecmp(v->name, "layer2_persistence")) {
19363 if (!strcasecmp(v->value, "keep_up")) {
19364 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
19365 } else if (!strcasecmp(v->value, "leave_down")) {
19366 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
19367 } else {
19368 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
19369 }
19370#endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
19371 } else if (!strcasecmp(v->name, "colp_send")) {
19372 if (!strcasecmp(v->value, "block")) {
19373 confp->pri.pri.colp_send = SIG_PRI_COLP_BLOCK;
19374 } else if (!strcasecmp(v->value, "connect")) {
19375 confp->pri.pri.colp_send = SIG_PRI_COLP_CONNECT;
19376 } else if (!strcasecmp(v->value, "update")) {
19377 confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
19378 } else {
19379 confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
19380 }
19381#endif /* HAVE_PRI */
19382#if defined(HAVE_SS7)
19383 } else if (!strcasecmp(v->name, "ss7type")) {
19384 if (!strcasecmp(v->value, "itu")) {
19385 cur_ss7type = SS7_ITU;
19386 } else if (!strcasecmp(v->value, "ansi")) {
19387 cur_ss7type = SS7_ANSI;
19388 } else {
19389 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
19390 }
19391 } else if (!strcasecmp(v->name, "slc")) {
19392 cur_slc = atoi(v->value);
19393 } else if (!strcasecmp(v->name, "linkset")) {
19394 cur_linkset = atoi(v->value);
19395 } else if (!strcasecmp(v->name, "pointcode")) {
19396 cur_pointcode = parse_pointcode(v->value);
19397 } else if (!strcasecmp(v->name, "adjpointcode")) {
19398 cur_adjpointcode = parse_pointcode(v->value);
19399 } else if (!strcasecmp(v->name, "defaultdpc")) {
19400 cur_defaultdpc = parse_pointcode(v->value);
19401 } else if (!strcasecmp(v->name, "cicbeginswith")) {
19402 cur_cicbeginswith = atoi(v->value);
19403 } else if (!strcasecmp(v->name, "networkindicator")) {
19404 if (!strcasecmp(v->value, "national")) {
19405 cur_networkindicator = SS7_NI_NAT;
19406 } else if (!strcasecmp(v->value, "national_spare")) {
19407 cur_networkindicator = SS7_NI_NAT_SPARE;
19408 } else if (!strcasecmp(v->value, "international")) {
19409 cur_networkindicator = SS7_NI_INT;
19410 } else if (!strcasecmp(v->value, "international_spare")) {
19411 cur_networkindicator = SS7_NI_INT_SPARE;
19412 } else {
19413 cur_networkindicator = -1;
19414 }
19415 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
19416 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
19417 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
19418 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
19419 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
19420 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
19421 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
19422 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
19423 } else if (!strcasecmp(v->name, "ss7_networkroutedprefix")) {
19424 ast_copy_string(confp->ss7.ss7.networkroutedprefix, v->value, sizeof(confp->ss7.ss7.networkroutedprefix));
19425 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
19426 if (!strcasecmp(v->value, "national")) {
19427 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
19428 } else if (!strcasecmp(v->value, "international")) {
19429 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
19430 } else if (!strcasecmp(v->value, "subscriber")) {
19431 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
19432 } else if (!strcasecmp(v->value, "unknown")) {
19433 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
19434 } else if (!strcasecmp(v->value, "dynamic")) {
19435 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
19436 } else {
19437 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
19438 }
19439 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
19440 if (!strcasecmp(v->value, "national")) {
19441 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
19442 } else if (!strcasecmp(v->value, "international")) {
19443 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
19444 } else if (!strcasecmp(v->value, "subscriber")) {
19445 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
19446 } else if (!strcasecmp(v->value, "unknown")) {
19447 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
19448 } else if (!strcasecmp(v->value, "dynamic")) {
19449 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
19450 } else {
19451 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
19452 }
19453 } else if (!strcasecmp(v->name, "sigchan")) {
19454 int sigchan, res;
19455 sigchan = atoi(v->value);
19456 res = linkset_addsigchan(sigchan);
19457 if (res < 0) {
19458 return -1;
19459 }
19460 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
19461 struct dahdi_ss7 *link;
19462 link = ss7_resolve_linkset(cur_linkset);
19463 if (!link) {
19464 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19465 return -1;
19466 }
19467 if (ast_true(v->value)) {
19468 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
19469 } else {
19470 link->ss7.flags &= ~LINKSET_FLAG_EXPLICITACM;
19471 }
19472 } else if (!strcasecmp(v->name, "ss7_autoacm")) {
19473 struct dahdi_ss7 *link;
19474 link = ss7_resolve_linkset(cur_linkset);
19475 if (!link) {
19476 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19477 return -1;
19478 }
19479 if (ast_true(v->value)) {
19480 link->ss7.flags |= LINKSET_FLAG_AUTOACM;
19481 } else {
19482 link->ss7.flags &= ~LINKSET_FLAG_AUTOACM;
19483 }
19484 } else if (!strcasecmp(v->name, "ss7_initialhwblo")) {
19485 struct dahdi_ss7 *link;
19486 link = ss7_resolve_linkset(cur_linkset);
19487 if (!link) {
19488 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19489 return -1;
19490 }
19491 if (ast_true(v->value)) {
19492 link->ss7.flags |= LINKSET_FLAG_INITIALHWBLO;
19493 } else {
19494 link->ss7.flags &= ~LINKSET_FLAG_INITIALHWBLO;
19495 }
19496 } else if (!strcasecmp(v->name, "ss7_use_echocontrol")) {
19497 struct dahdi_ss7 *link;
19498 link = ss7_resolve_linkset(cur_linkset);
19499 if (!link) {
19500 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19501 return -1;
19502 }
19503 if (ast_true(v->value)) {
19504 link->ss7.flags |= LINKSET_FLAG_USEECHOCONTROL;
19505 } else {
19506 link->ss7.flags &= ~LINKSET_FLAG_USEECHOCONTROL;
19507 }
19508 } else if (!strcasecmp(v->name, "ss7_default_echocontrol")) {
19509 struct dahdi_ss7 *link;
19510 link = ss7_resolve_linkset(cur_linkset);
19511 if (!link) {
19512 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19513 return -1;
19514 }
19515 if (ast_true(v->value)) {
19516 link->ss7.flags |= LINKSET_FLAG_DEFAULTECHOCONTROL;
19517 } else {
19518 link->ss7.flags &= ~LINKSET_FLAG_DEFAULTECHOCONTROL;
19519 }
19520 } else if (!strncasecmp(v->name, "isup_timer.", 11)) {
19521 struct dahdi_ss7 *link;
19522 link = ss7_resolve_linkset(cur_linkset);
19523 if (!link) {
19524 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19525 return -1;
19526 }
19527 if (!link->ss7.ss7) {
19528 ast_log(LOG_ERROR, "Please specify isup timers after sigchan!\n");
19529 } else if (!ss7_set_isup_timer(link->ss7.ss7, strstr(v->name, ".") + 1, atoi(v->value))) {
19530 ast_log(LOG_ERROR, "Invalid isup timer %s\n", v->name);
19531 }
19532 } else if (!strncasecmp(v->name, "mtp3_timer.", 11)) {
19533 struct dahdi_ss7 *link;
19534 link = ss7_resolve_linkset(cur_linkset);
19535 if (!link) {
19536 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19537 return -1;
19538 }
19539 if (!link->ss7.ss7) {
19540 ast_log(LOG_ERROR, "Please specify mtp3 timers after sigchan!\n");
19541 } else if (!ss7_set_mtp3_timer(link->ss7.ss7, strstr(v->name, ".") + 1, atoi(v->value))) {
19542 ast_log(LOG_ERROR, "Invalid mtp3 timer %s\n", v->name);
19543 }
19544 } else if (!strcasecmp(v->name, "inr_if_no_calling")) {
19545 struct dahdi_ss7 *link;
19546 link = ss7_resolve_linkset(cur_linkset);
19547 if (!link) {
19548 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19549 return -1;
19550 }
19551 if (!link->ss7.ss7) {
19552 ast_log(LOG_ERROR, "Please specify inr_if_no_calling after sigchan!\n");
19553 } else if (ast_true(v->value)) {
19554 ss7_set_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
19555 } else {
19556 ss7_clear_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
19557 }
19558 } else if (!strcasecmp(v->name, "non_isdn_access")) {
19559 struct dahdi_ss7 *link;
19560 link = ss7_resolve_linkset(cur_linkset);
19561 if (!link) {
19562 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19563 return -1;
19564 }
19565 if (!link->ss7.ss7) {
19566 ast_log(LOG_ERROR, "Please specify non_isdn_access after sigchan!\n");
19567 } else if (ast_true(v->value)) {
19568 ss7_clear_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
19569 } else {
19570 ss7_set_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
19571 }
19572 } else if (!strcasecmp(v->name, "sls_shift")) {
19573 struct dahdi_ss7 *link;
19574 int sls_shift = atoi(v->value);
19575
19576 if (sls_shift < 0 || sls_shift > 7) {
19577 ast_log(LOG_ERROR, "Invalid sls_shift value. Must be between 0 and 7\n");
19578 return -1;
19579 }
19580
19581 link = ss7_resolve_linkset(cur_linkset);
19582 if (!link) {
19583 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19584 return -1;
19585 }
19586 if (!link->ss7.ss7) {
19587 ast_log(LOG_ERROR, "Please specify sls_shift after sigchan!\n");
19588 } else {
19589 ss7_set_sls_shift(link->ss7.ss7, sls_shift);
19590 }
19591 } else if (!strcasecmp(v->name, "cause_location")) {
19592 struct dahdi_ss7 *link;
19593 int cause_location = atoi(v->value);
19594
19595 if (cause_location < 0 || cause_location > 15) {
19596 ast_log(LOG_ERROR, "Invalid cause_location value. Must be between 0 and 15\n");
19597 return -1;
19598 }
19599 link = ss7_resolve_linkset(cur_linkset);
19600 if (!link) {
19601 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19602 return -1;
19603 }
19604 if (!link->ss7.ss7) {
19605 ast_log(LOG_ERROR, "Please specify cause_location after sigchan!\n");
19606 } else {
19607 ss7_set_cause_location(link->ss7.ss7, cause_location);
19608 }
19609#endif /* defined(HAVE_SS7) */
19610#ifdef HAVE_OPENR2
19611 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
19612 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
19613 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);
19614 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
19615 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
19616 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
19617 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
19618 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
19619 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
19620 confp->mfcr2.variant = OR2_VAR_ITU;
19621 }
19622 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
19623 confp->mfcr2.mfback_timeout = atoi(v->value);
19624 if (!confp->mfcr2.mfback_timeout) {
19625 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
19626 confp->mfcr2.mfback_timeout = -1;
19627 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
19628 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
19629 }
19630 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
19631 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
19632 if (confp->mfcr2.metering_pulse_timeout > 500) {
19633 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
19634 }
19635#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
19636 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
19637 confp->mfcr2.dtmf_detection = ast_true(v->value) ? 1 : 0;
19638 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
19639 confp->mfcr2.dtmf_dialing = ast_true(v->value) ? 1 : 0;
19640 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
19641 confp->mfcr2.dtmf_time_on = atoi(v->value);
19642 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
19643 confp->mfcr2.dtmf_time_off = atoi(v->value);
19644#endif
19645#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
19646 } else if (!strcasecmp(v->name, "mfcr2_dtmf_end_timeout")) {
19647 confp->mfcr2.dtmf_end_timeout = atoi(v->value);
19648#endif
19649 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
19650 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
19651 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
19652 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
19653 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
19654 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
19655 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
19656 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
19657 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
19658 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
19659 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
19660 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
19661 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
19662 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
19663#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
19664 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
19665 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
19666#endif
19667 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
19668 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
19669 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
19670 confp->mfcr2.max_ani = atoi(v->value);
19671 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION) {
19672 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
19673 }
19674 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
19675 confp->mfcr2.max_dnis = atoi(v->value);
19676 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION) {
19677 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
19678 }
19679 } else if (!strcasecmp(v->name, "mfcr2_category")) {
19680 confp->mfcr2.category = openr2_proto_get_category(v->value);
19681 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
19682 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
19683 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
19684 v->value, v->lineno);
19685 }
19686 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
19687 openr2_log_level_t tmplevel;
19688 char *clevel;
19689 char *logval;
19690 char copy[strlen(v->value) + 1];
19691 strcpy(copy, v->value); /* safe */
19692 logval = copy;
19693 while (logval) {
19694 clevel = strsep(&logval,",");
19695 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
19696 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
19697 continue;
19698 }
19699 confp->mfcr2.loglevel |= tmplevel;
19700 }
19701#endif /* HAVE_OPENR2 */
19702 } else if (!strcasecmp(v->name, "cadence")) {
19703 /* setup to scan our argument */
19704 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
19705 int i;
19706 struct dahdi_ring_cadence new_cadence;
19707 int cid_location = -1;
19708 int firstcadencepos = 0;
19709 char original_args[80];
19710 int cadence_is_ok = 1;
19711
19712 ast_copy_string(original_args, v->value, sizeof(original_args));
19713 /* 16 cadences allowed (8 pairs) */
19714 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]);
19715
19716 /* Cadence must be even (on/off) */
19717 if (element_count % 2 == 1) {
19718 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
19719 cadence_is_ok = 0;
19720 }
19721
19722 /* This check is only needed to satisfy the compiler that element_count can't cause an out of bounds */
19723 if (element_count > ARRAY_LEN(c)) {
19724 element_count = ARRAY_LEN(c);
19725 }
19726
19727 /* Ring cadences cannot be negative */
19728 for (i = 0; i < element_count; i++) {
19729 if (c[i] == 0) {
19730 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
19731 cadence_is_ok = 0;
19732 break;
19733 } else if (c[i] < 0) {
19734 if (i % 2 == 1) {
19735 /* Silence duration, negative possibly okay */
19736 if (cid_location == -1) {
19737 cid_location = i;
19738 c[i] *= -1;
19739 } else {
19740 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
19741 cadence_is_ok = 0;
19742 break;
19743 }
19744 } else {
19745 if (firstcadencepos == 0) {
19746 firstcadencepos = i; /* only recorded to avoid duplicate specification */
19747 /* duration will be passed negative to the DAHDI driver */
19748 } else {
19749 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
19750 cadence_is_ok = 0;
19751 break;
19752 }
19753 }
19754 }
19755 }
19756
19757 /* Substitute our scanned cadence */
19758 for (i = 0; i < 16; i++) {
19759 new_cadence.ringcadence[i] = c[i];
19760 }
19761
19762 if (cadence_is_ok) {
19763 /* ---we scanned it without getting annoyed; now some sanity checks--- */
19764 if (element_count < 2) {
19765 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
19766 } else {
19767 if (cid_location == -1) {
19768 /* user didn't say; default to first pause */
19769 cid_location = 1;
19770 } else {
19771 /* convert element_index to cidrings value */
19772 cid_location = (cid_location + 1) / 2;
19773 }
19774 /* ---we like their cadence; try to install it--- */
19776 /* this is the first user-defined cadence; clear the default user cadences */
19777 num_cadence = 0;
19778 if ((num_cadence+1) >= NUM_CADENCE_MAX)
19779 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
19780 else {
19781 cadences[num_cadence] = new_cadence;
19782 cidrings[num_cadence++] = cid_location;
19783 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
19784 }
19785 }
19786 }
19787 } else if (!strcasecmp(v->name, "ringtimeout")) {
19788 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
19789 } else if (!strcasecmp(v->name, "prewink")) {
19790 confp->timing.prewinktime = atoi(v->value);
19791 } else if (!strcasecmp(v->name, "preflash")) {
19792 confp->timing.preflashtime = atoi(v->value);
19793 } else if (!strcasecmp(v->name, "wink")) {
19794 confp->timing.winktime = atoi(v->value);
19795 } else if (!strcasecmp(v->name, "flash")) {
19796 confp->timing.flashtime = atoi(v->value);
19797 } else if (!strcasecmp(v->name, "start")) {
19798 confp->timing.starttime = atoi(v->value);
19799 } else if (!strcasecmp(v->name, "rxwink")) {
19800 confp->timing.rxwinktime = atoi(v->value);
19801 } else if (!strcasecmp(v->name, "rxflash")) {
19802 confp->timing.rxflashtime = atoi(v->value);
19803 } else if (!strcasecmp(v->name, "debounce")) {
19804 confp->timing.debouncetime = atoi(v->value);
19805 } else if (!strcasecmp(v->name, "toneduration")) {
19806 int toneduration;
19807 int ctlfd;
19808 int res;
19809 struct dahdi_dialparams dps;
19810
19811 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
19812 if (ctlfd == -1) {
19813 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
19814 return -1;
19815 }
19816
19817 toneduration = atoi(v->value);
19818 if (toneduration > -1) {
19819 memset(&dps, 0, sizeof(dps));
19820
19821 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
19822 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
19823 if (res < 0) {
19824 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
19825 close(ctlfd);
19826 return -1;
19827 }
19828 }
19829 close(ctlfd);
19830 } else if (!strcasecmp(v->name, "defaultcic")) {
19832 } else if (!strcasecmp(v->name, "defaultozz")) {
19834 } else if (!strcasecmp(v->name, "mwilevel")) {
19835 mwilevel = atoi(v->value);
19836 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
19837 dtmfcid_level = atoi(v->value);
19838 } else if (!strcasecmp(v->name, "reportalarms")) {
19839 if (!strcasecmp(v->value, "all"))
19841 if (!strcasecmp(v->value, "none"))
19842 report_alarms = 0;
19843 else if (!strcasecmp(v->value, "channels"))
19845 else if (!strcasecmp(v->value, "spans"))
19847 }
19848 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
19849 ast_log(LOG_NOTICE, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
19850 }
19851
19852 if (dahdichan) {
19853 /* Process the deferred dahdichan value. */
19854 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno)) {
19855 if (confp->ignore_failed_channels) {
19857 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
19858 dahdichan->value);
19859 } else {
19860 return -1;
19861 }
19862 }
19863 }
19864
19865 /*
19866 * Since confp has already filled individual dahdi_pvt objects with channels
19867 * at this point, clear the variables in confp's pvt.
19868 */
19869 if (confp->chan.vars) {
19871 confp->chan.vars = NULL;
19872 }
19873
19874 /* mark the first channels of each DAHDI span to watch for their span alarms */
19875 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
19876 if (!tmp->destroy && tmp->span != y) {
19877 tmp->manages_span_alarms = 1;
19878 y = tmp->span;
19879 } else {
19880 tmp->manages_span_alarms = 0;
19881 }
19882 }
19883
19884 /*< \todo why check for the pseudo in the per-channel section.
19885 * Any actual use for manual setup of the pseudo channel? */
19886 if (!has_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
19887 /* use the default configuration for a channel, so
19888 that any settings from real configured channels
19889 don't "leak" into the pseudo channel config
19890 */
19892
19893 if (conf.chan.cc_params) {
19895 } else {
19896 tmp = NULL;
19897 }
19898 if (tmp) {
19899 ast_verb(3, "Automatically generated pseudo channel\n");
19900 has_pseudo = 1;
19901 } else {
19902 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
19903 }
19904 ast_cc_config_params_destroy(conf.chan.cc_params);
19905 }
19906
19907 /* Since named callgroup and named pickup group are ref'd to dahdi_pvt at this point, unref container in confp's pvt. */
19910
19911 return 0;
19912}
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
Definition: abstract_jb.c:545
static int copy(char *infile, char *outfile)
Utility function to copy a file.
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1193
int ast_cc_is_config_param(const char *const name)
Is this a CCSS configuration parameter?
Definition: ccss.c:840
int ast_cc_set_param(struct ast_cc_config_params *params, const char *const name, const char *value)
set a CCSS configuration parameter, given its name
Definition: ccss.c:801
static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno)
Definition: chan_dahdi.c:18226
static int user_has_defined_cadences
Definition: chan_dahdi.c:686
#define PROC_DAHDI_OPT_NOCHAN
Definition: chan_dahdi.c:18420
static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
Definition: chan_dahdi.c:18424
static char defaultcic[64]
Definition: chan_dahdi.c:717
static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
Definition: chan_dahdi.c:18287
#define DEFAULT_DIALTONE_DETECT_TIMEOUT
Definition: chan_dahdi.c:805
#define PROC_DAHDI_OPT_NOWARN
Definition: chan_dahdi.c:18422
static char defaultozz[64]
Definition: chan_dahdi.c:718
#define NUM_CADENCE_MAX
Definition: chan_dahdi.c:684
static struct ast_timer * timer
Definition: chan_iax2.c:364
struct ast_namedgroups * ast_get_namedgroups(const char *s)
Create an ast_namedgroups set with group names from comma separated string.
Definition: channel.c:7675
enum ama_flags ast_channel_string2amaflag(const char *flag)
Convert a string to a detail record AMA flag.
Definition: channel.c:4360
ast_group_t ast_get_group(const char *s)
Definition: channel.c:7618
char * strcasestr(const char *, const char *)
@ SIG_PRI_COLP_CONNECT
Definition: sig_pri.h:439
@ SIG_PRI_COLP_BLOCK
Definition: sig_pri.h:437
#define DAHDI_OVERLAPDIAL_BOTH
Definition: sig_pri.h:254
#define SIG_PRI_AOC_GRANT_D
Definition: sig_pri.h:54
#define DAHDI_OVERLAPDIAL_NONE
Definition: sig_pri.h:251
#define DAHDI_CHAN_MAPPING_LOGICAL
Definition: sig_pri.h:248
@ SIG_PRI_MOH_SIGNALING_MOH
Definition: sig_pri.h:75
@ SIG_PRI_MOH_SIGNALING_NOTIFY
Definition: sig_pri.h:77
#define SIG_PRI_AOC_GRANT_E
Definition: sig_pri.h:55
#define SIG_PRI_AOC_GRANT_S
Definition: sig_pri.h:53
#define LINKSET_FLAG_EXPLICITACM
Definition: sig_ss7.h:68
#define LINKSET_FLAG_AUTOACM
Definition: sig_ss7.h:72
#define LINKSET_FLAG_DEFAULTECHOCONTROL
Definition: sig_ss7.h:71
#define LINKSET_FLAG_USEECHOCONTROL
Definition: sig_ss7.h:70
#define SS7_NAI_DYNAMIC
Definition: sig_ss7.h:66
char smdi_port[SMDI_MAX_FILENAME_LEN]
The serial port to listen for SMDI data on.
Definition: chan_dahdi.c:974
int ignore_failed_channels
Definition: chan_dahdi.c:968
struct dahdi_params timing
Definition: chan_dahdi.c:965
unsigned int immediatering
TRUE if audible ringback should be provided when immediate = yes.
Definition: chan_dahdi.h:322
unsigned int threewaysilenthold
TRUE if a three way dial tone should time out to silence.
Definition: chan_dahdi.h:373
unsigned int hwtxgain_enabled
TRUE if hardware Tx gain set by Asterisk.
Definition: chan_dahdi.h:469
unsigned int ani_wink_time
INTEGER, length of time to wait before sending ANI wink in ms.
Definition: chan_dahdi.h:200
unsigned int use_callingpres
TRUE if we will use the calling presentation setting from the Asterisk channel for outgoing calls.
Definition: chan_dahdi.h:397
unsigned int priexclusive
TRUE if PRI B channels are always exclusively selected.
Definition: chan_dahdi.h:349
float hwrxgain
Hardware Rx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:154
int tonezone
Definition: chan_dahdi.h:167
float hwtxgain
Hardware Tx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:156
char description[32]
A description for the channel configuration.
Definition: chan_dahdi.h:496
unsigned int hwrxgain_enabled
TRUE if hardware Rx gain set by Asterisk.
Definition: chan_dahdi.h:467
unsigned int ani_timeout
INTEGER, length of ANI failure timeout in ms.
Definition: chan_dahdi.h:195
unsigned int restrictcid
TRUE if caller ID is restricted.
Definition: chan_dahdi.h:363
unsigned int priindication_oob
TRUE if PRI congestion/busy indications are sent out-of-band.
Definition: chan_dahdi.h:344
unsigned int ani_info_digits
INTEGER, number of ANI INFO digits on a CAMA trunk. older switches use 1 INFO digit,...
Definition: chan_dahdi.h:190
unsigned int hidecalleridname
TRUE if hide just the name not the number for legacy PBX use.
Definition: chan_dahdi.h:308
unsigned int echocanbridged
TRUE if echo cancellation enabled when bridged.
Definition: chan_dahdi.h:270
unsigned int calledsubscriberheld
TRUE if Called Subscriber held is enabled. This allows a single incoming call to hold a DAHDI channel...
Definition: chan_dahdi.h:213
static struct test_options options

References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, ANALOG_DIALMODE_BOTH, ANALOG_DIALMODE_DTMF, ANALOG_DIALMODE_NONE, ANALOG_DIALMODE_PULSE, ANALOG_FIRST_DIGIT_TIMEOUT, ANALOG_INTER_DIGIT_TIMEOUT, ANALOG_MATCH_DIGIT_TIMEOUT, dahdi_pvt::ani_info_digits, dahdi_pvt::ani_timeout, dahdi_pvt::ani_wink_time, dahdi_pvt::answeronpolarityswitch, ARRAY_LEN, ast_callerid_split(), ast_cc_config_params_destroy(), ast_cc_is_config_param(), ast_cc_set_param(), ast_channel_string2amaflag(), ast_copy_string(), ast_debug, ast_false(), ast_get_group(), ast_get_namedgroups(), ast_jb_read_conf(), ast_log, AST_MAX_EXTENSION, ast_strlen_zero(), ast_true(), ast_unref_namedgroups(), ast_variable_list_replace(), 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, c, cadences, dahdi_pvt::calledsubscriberheld, dahdi_pvt::callgroup, dahdi_pvt::callprogress, 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, cidrings, dahdi_pvt::context, ringContextData::contextData, copy(), 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, DEFAULT_DIALTONE_DETECT_TIMEOUT, defaultcic, defaultozz, dahdi_pvt::description, dahdi_pvt::dialmode, dahdi_pvt::dialtone_detect, distinctiveringaftercid, dahdi_pvt::drings, DSP_DIGITMODE_RELAXDTMF, dtmfcid_level, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echotraining, errno, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxdetect_timeout, dahdi_pvt::firstdigit_timeout, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, has_pseudo, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pvt::hwrxgain, dahdi_pvt::hwrxgain_enabled, dahdi_pvt::hwtxgain, dahdi_pvt::hwtxgain_enabled, iflist, dahdi_chan_conf::ignore_failed_channels, dahdi_pvt::immediate, dahdi_pvt::immediatering, dahdi_pvt::interdigit_timeout, dahdi_chan_conf::is_sig_auto, dahdi_pvt::language, ast_variable::lineno, LINKSET_FLAG_AUTOACM, LINKSET_FLAG_DEFAULTECHOCONTROL, LINKSET_FLAG_EXPLICITACM, LINKSET_FLAG_INITIALHWBLO, LINKSET_FLAG_USEECHOCONTROL, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::matchdigit_timeout, mkintf(), dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, mwilevel, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, mwimonitornotify, mwisend_rpas, ast_variable::name, dahdi_pvt::named_callgroups, dahdi_pvt::named_pickupgroups, ast_variable::next, NULL, num_cadence, NUM_CADENCE_MAX, NUM_SPANS, numbufs, options, 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(), progzone, dahdi_pvt::pulse, dahdi_pvt::radio, distRingData::range, READ_SIZE, reload(), dahdi_pvt::reoriginate, report_alarms, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, ringt_base, 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_COLP_BLOCK, SIG_PRI_COLP_CONNECT, SIG_PRI_COLP_UPDATE, SIG_PRI_MOH_SIGNALING_MOH, SIG_PRI_MOH_SIGNALING_NOTIFY, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, SIG_SS7, dahdi_chan_conf::smdi_port, SS7_NAI_DYNAMIC, strcasestr(), dahdi_pvt::stripmsd, strsep(), dahdi_pvt::threewaycalling, dahdi_pvt::threewaysilenthold, timer, dahdi_chan_conf::timing, tmp(), 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, usedistinctiveringdetection, dahdi_pvt::usefaxbuffers, user_has_defined_cadences, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

Referenced by setup_dahdi_int().

◆ process_echocancel()

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

Definition at line 18287 of file chan_dahdi.c.

18288{
18289 char *parse = ast_strdupa(data);
18290 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
18291 unsigned int param_count;
18292 unsigned int x;
18293
18294 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
18295 return;
18296
18297 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
18298
18299 /* first parameter is tap length, process it here */
18300
18301 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
18302
18303 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
18304 confp->chan.echocancel.head.tap_length = x;
18305 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
18306 confp->chan.echocancel.head.tap_length = 128;
18307
18308 /* now process any remaining parameters */
18309
18310 for (x = 1; x < param_count; x++) {
18311 struct {
18312 char *name;
18313 char *value;
18314 } param;
18315
18316 if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
18317 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
18318 continue;
18319 }
18320
18321 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
18322 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
18323 continue;
18324 }
18325
18326 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
18327
18328 if (param.value) {
18329 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
18330 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
18331 continue;
18332 }
18333 }
18334 confp->chan.echocancel.head.param_count++;
18335 }
18336}
#define ast_app_separate_args(a, b, c, d)
struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS]
Definition: chan_dahdi.h:628

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

◆ publish_channel_alarm()

static void publish_channel_alarm ( int  channel,
const char *  alarm_txt 
)
static

Definition at line 7696 of file chan_dahdi.c.

7697{
7698 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7699 RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
7700 if (!dahdi_chan) {
7701 return;
7702 }
7703
7704 ast_str_set(&dahdi_chan, 0, "%d", channel);
7705 body = ast_json_pack("{s: s, s: s}",
7706 "DAHDIChannel", ast_str_buffer(dahdi_chan),
7707 "Alarm", alarm_txt);
7708 if (!body) {
7709 return;
7710 }
7711
7713}
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
Definition: manager.c:2055
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612

References ast_free, ast_json_pack(), ast_json_unref(), ast_manager_publish_event(), ast_str_buffer(), ast_str_create, ast_str_set(), EVENT_FLAG_SYSTEM, NULL, and RAII_VAR.

Referenced by handle_alarms().

◆ publish_channel_alarm_clear()

static void publish_channel_alarm_clear ( int  channel)
static

Definition at line 3753 of file chan_dahdi.c.

3754{
3755 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3756 RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
3757 if (!dahdi_chan) {
3758 return;
3759 }
3760
3761 ast_str_set(&dahdi_chan, 0, "%d", channel);
3762 ast_log(LOG_NOTICE, "Alarm cleared on channel DAHDI/%d\n", channel);
3763 body = ast_json_pack("{s: s}", "DAHDIChannel", ast_str_buffer(dahdi_chan));
3764 if (!body) {
3765 return;
3766 }
3767
3768 ast_manager_publish_event("AlarmClear", EVENT_FLAG_SYSTEM, body);
3769}

References ast_free, ast_json_pack(), ast_json_unref(), ast_log, ast_manager_publish_event(), ast_str_buffer(), ast_str_create, ast_str_set(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, LOG_NOTICE, NULL, and RAII_VAR.

Referenced by handle_clear_alarms().

◆ publish_dahdichannel()

static void publish_dahdichannel ( struct ast_channel chan,
ast_group_t  group,
int  span,
const char *  dahdi_channel 
)
static

Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages.

Definition at line 1929 of file chan_dahdi.c.

1930{
1931 RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
1932
1933 ast_assert(dahdi_channel != NULL);
1934
1935 blob = ast_json_pack("{s: I, s: i, s: s}",
1936 "group", (ast_json_int_t)group,
1937 "span", span,
1938 "channel", dahdi_channel);
1939 if (!blob) {
1940 return;
1941 }
1942
1943 ast_channel_lock(chan);
1944 ast_channel_publish_blob(chan, dahdichannel_type(), blob);
1945 ast_channel_unlock(chan);
1946}
void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message.
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition: json.h:87
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_channel_lock, ast_channel_publish_blob(), ast_channel_unlock, ast_json_pack(), ast_json_unref(), NULL, and RAII_VAR.

Referenced by dahdi_ami_channel_event().

◆ publish_dnd_state()

static void publish_dnd_state ( int  channel,
const char *  status 
)
static

Definition at line 9802 of file chan_dahdi.c.

9803{
9804 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
9805 RAII_VAR(struct ast_str *, dahdichan, ast_str_create(32), ast_free);
9806 if (!dahdichan) {
9807 return;
9808 }
9809
9810 ast_str_set(&dahdichan, 0, "%d", channel);
9811
9812 body = ast_json_pack("{s: s, s: s}",
9813 "DAHDIChannel", ast_str_buffer(dahdichan),
9814 "Status", status);
9815 if (!body) {
9816 return;
9817 }
9818
9820}
jack_status_t status
Definition: app_jack.c:146

References ast_free, ast_json_pack(), ast_json_unref(), ast_manager_publish_event(), ast_str_buffer(), ast_str_create, ast_str_set(), EVENT_FLAG_SYSTEM, NULL, RAII_VAR, and status.

Referenced by dahdi_dnd().

◆ publish_span_alarm()

static void publish_span_alarm ( int  span,
const char *  alarm_txt 
)
static

Definition at line 7682 of file chan_dahdi.c.

7683{
7684 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7685
7686 body = ast_json_pack("{s: i, s: s}",
7687 "Span", span,
7688 "Alarm", alarm_txt);
7689 if (!body) {
7690 return;
7691 }
7692
7693 ast_manager_publish_event("SpanAlarm", EVENT_FLAG_SYSTEM, body);
7694}

References ast_json_pack(), ast_json_unref(), ast_manager_publish_event(), EVENT_FLAG_SYSTEM, NULL, and RAII_VAR.

Referenced by handle_alarms().

◆ publish_span_alarm_clear()

static void publish_span_alarm_clear ( int  span)
static

Definition at line 3771 of file chan_dahdi.c.

3772{
3773 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3774
3775 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", span);
3776 body = ast_json_pack("{s: i}", "Span", span);
3777 if (!body) {
3778 return;
3779 }
3780
3781 ast_manager_publish_event("SpanAlarmClear", EVENT_FLAG_SYSTEM, body);
3782}

References ast_json_pack(), ast_json_unref(), ast_log, ast_manager_publish_event(), EVENT_FLAG_SYSTEM, LOG_NOTICE, NULL, RAII_VAR, and dahdi_pvt::span.

Referenced by handle_clear_alarms().

◆ release_doomed_pris()

static void release_doomed_pris ( void  )
static

Definition at line 1283 of file chan_dahdi.c.

1284{
1285#ifdef HAVE_PRI
1286 struct doomed_pri *entry;
1287
1288 AST_LIST_LOCK(&doomed_pris);
1289 while ((entry = AST_LIST_REMOVE_HEAD(&doomed_pris, list))) {
1290 /* The span destruction must be done with this lock not held */
1291 AST_LIST_UNLOCK(&doomed_pris);
1292 ast_debug(4, "Destroying span %d from doomed queue.\n",
1293 entry->pri->span);
1294 pri_destroy_span(entry->pri);
1295 ast_free(entry);
1296 AST_LIST_LOCK(&doomed_pris);
1297 }
1298 AST_LIST_UNLOCK(&doomed_pris);
1299#endif
1300}
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
Definition: search.h:40

References ast_debug, ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, and AST_LIST_UNLOCK.

Referenced by do_monitor().

◆ reload()

static int reload ( void  )
static

Definition at line 20497 of file chan_dahdi.c.

20498{
20499 int res = 0;
20500
20501 res = setup_dahdi(1);
20502 if (res) {
20503 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
20504 return -1;
20505 }
20506 return 0;
20507}

References ast_log, LOG_WARNING, and setup_dahdi().

Referenced by build_channels(), process_dahdi(), setup_dahdi(), and setup_dahdi_int().

◆ reset_conf()

static int reset_conf ( struct dahdi_pvt p)
static

Definition at line 4817 of file chan_dahdi.c.

4818{
4819 p->confno = -1;
4820 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
4821 if (p->subs[SUB_REAL].dfd > -1) {
4822 struct dahdi_confinfo zi;
4823
4824 memset(&zi, 0, sizeof(zi));
4825 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
4826 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
4827 }
4828 return 0;
4829}

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

◆ restart_monitor()

static int restart_monitor ( void  )
static

Definition at line 12156 of file chan_dahdi.c.

12157{
12158 /* If we're supposed to be stopped -- stay stopped */
12160 return 0;
12162 if (monitor_thread == pthread_self()) {
12164 ast_log(LOG_WARNING, "Cannot kill myself\n");
12165 return -1;
12166 }
12168 /* Wake up the thread */
12169 pthread_kill(monitor_thread, SIGURG);
12170 } else {
12171 /* Start a new monitor */
12174 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12175 return -1;
12176 }
12177 }
12179 return 0;
12180}
static void * do_monitor(void *data)
Definition: chan_dahdi.c:11847

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, monitor_thread, monlock, and NULL.

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

◆ restore_conference()

static int restore_conference ( struct dahdi_pvt p)
static

Definition at line 5250 of file chan_dahdi.c.

5251{
5252 int res;
5253 if (p->saveconf.confmode) {
5254 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
5255 p->saveconf.confmode = 0;
5256 if (res) {
5257 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
5258 return -1;
5259 }
5260 ast_debug(1, "Restored conferencing\n");
5261 }
5262 return 0;
5263}
struct dahdi_confinfo saveconf
Definition: chan_dahdi.h:132

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

◆ restore_gains()

static int restore_gains ( struct dahdi_pvt p)
static

Definition at line 5157 of file chan_dahdi.c.

5158{
5159 int res;
5160
5161 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5162 if (res) {
5163 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
5164 return -1;
5165 }
5166
5167 return 0;
5168}

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

◆ revert_fax_buffers()

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

Definition at line 6216 of file chan_dahdi.c.

6217{
6218 if (p->bufferoverrideinuse) {
6219 /* faxbuffers are in use, revert them */
6220 struct dahdi_bufferinfo bi = {
6221 .txbufpolicy = p->buf_policy,
6222 .rxbufpolicy = p->buf_policy,
6223 .bufsize = p->bufsize,
6224 .numbufs = p->buf_no
6225 };
6226 int bpres;
6227
6228 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
6229 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
6230 }
6231 p->bufferoverrideinuse = 0;
6232 return bpres;
6233 }
6234
6235 return -1;
6236}

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

◆ save_conference()

static int save_conference ( struct dahdi_pvt p)
static

Definition at line 5224 of file chan_dahdi.c.

5225{
5226 struct dahdi_confinfo c;
5227 int res;
5228 if (p->saveconf.confmode) {
5229 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
5230 return -1;
5231 }
5232 p->saveconf.chan = 0;
5233 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
5234 if (res) {
5235 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
5236 p->saveconf.confmode = 0;
5237 return -1;
5238 }
5239 memset(&c, 0, sizeof(c));
5240 c.confmode = DAHDI_CONF_NORMAL;
5241 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
5242 if (res) {
5243 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
5244 return -1;
5245 }
5246 ast_debug(1, "Disabled conferencing\n");
5247 return 0;
5248}

References ast_debug, ast_log, c, 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().

◆ send_callerid()

static int send_callerid ( struct dahdi_pvt p)
static

Definition at line 5311 of file chan_dahdi.c.

5312{
5313 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
5314 int res;
5315 /* Take out of linear mode if necessary */
5316 if (p->subs[SUB_REAL].linear) {
5317 p->subs[SUB_REAL].linear = 0;
5319 }
5320 while (p->cidpos < p->cidlen) {
5321 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
5322 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
5323 if (res < 0) {
5324 if (errno == EAGAIN)
5325 return 0;
5326 else {
5327 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5328 return -1;
5329 }
5330 }
5331 if (!res)
5332 return 0;
5333 p->cidpos += res;
5334 }
5336 ast_free(p->cidspill);
5337 p->cidspill = NULL;
5338 if (p->callwaitcas) {
5339 /* Wait for CID/CW to expire */
5342 } else
5344 return 0;
5345}
#define CALLWAITING_SUPPRESS_SAMPLES
Definition: chan_dahdi.c:801
#define CIDCW_EXPIRE_SAMPLES
Definition: chan_dahdi.c:802

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, NULL, restore_conference(), SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_callwait(), dahdi_read(), my_callwait(), my_send_callerid(), and send_cwcidspill().

◆ send_cwcidspill()

static int send_cwcidspill ( struct dahdi_pvt p)
static

Definition at line 5265 of file chan_dahdi.c.

5266{
5267 p->callwaitcas = 0;
5268 p->cidcwexpire = 0;
5269 p->cid_suppress_expire = 0;
5271 return -1;
5273 /* Make sure we account for the end */
5274 p->cidlen += READ_SIZE * 4;
5275 p->cidpos = 0;
5276 send_callerid(p);
5277 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
5278 return 0;
5279}
int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)
Definition: callerid.c:1143
char callwait_num[AST_MAX_EXTENSION]
Call waiting number.
Definition: chan_dahdi.h:541
char callwait_name[AST_MAX_EXTENSION]
Call waiting name.
Definition: chan_dahdi.h:543

References ast_callerid_callwaiting_generate(), AST_LAW, ast_malloc, ast_verb, dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, MAX_CALLERID_SIZE, READ_SIZE, and send_callerid().

Referenced by dahdi_handle_dtmf().

◆ set_actual_gain()

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

Definition at line 5138 of file chan_dahdi.c.

5139{
5140 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
5141}

References set_actual_rxgain(), and set_actual_txgain().

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

◆ set_actual_rxgain()

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

Definition at line 5121 of file chan_dahdi.c.

5122{
5123 struct dahdi_gains g;
5124 int res;
5125
5126 memset(&g, 0, sizeof(g));
5127 res = ioctl(fd, DAHDI_GETGAINS, &g);
5128 if (res) {
5129 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
5130 return res;
5131 }
5132
5133 fill_rxgain(&g, gain, drc, law);
5134
5135 return ioctl(fd, DAHDI_SETGAINS, &g);
5136}
static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
Definition: chan_dahdi.c:5056

References ast_debug, errno, and fill_rxgain().

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

◆ set_actual_txgain()

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

Definition at line 5104 of file chan_dahdi.c.

5105{
5106 struct dahdi_gains g;
5107 int res;
5108
5109 memset(&g, 0, sizeof(g));
5110 res = ioctl(fd, DAHDI_GETGAINS, &g);
5111 if (res) {
5112 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
5113 return res;
5114 }
5115
5116 fill_txgain(&g, gain, drc, law);
5117
5118 return ioctl(fd, DAHDI_SETGAINS, &g);
5119}
static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
Definition: chan_dahdi.c:5006

References ast_debug, errno, and fill_txgain().

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

◆ set_hwgain()

static int set_hwgain ( int  fd,
float  gain,
int  tx_direction 
)
static

Definition at line 4976 of file chan_dahdi.c.

4977{
4978 struct dahdi_hwgain hwgain;
4979
4980 hwgain.newgain = gain * 10.0;
4981 hwgain.tx = tx_direction;
4982 return ioctl(fd, DAHDI_SET_HWGAIN, &hwgain) < 0;
4983}

Referenced by dahdi_set_hwgain(), and mkintf().

◆ setup_dahdi()

static int setup_dahdi ( int  reload)
static

Definition at line 20238 of file chan_dahdi.c.

20239{
20240 int res;
20241 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
20242 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
20244
20245 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
20246 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
20247 } else {
20248 res = -1;
20249 }
20252 ast_cc_config_params_destroy(conf.chan.cc_params);
20253
20254 return res;
20255}

References ast_cc_config_params_destroy(), dahdi_pvt::cc_params, dahdi_chan_conf::chan, dahdi_chan_conf_default(), reload(), and setup_dahdi_int().

Referenced by dahdi_restart(), load_module(), and reload().

◆ setup_dahdi_int()

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

19945{
19946 struct ast_config *cfg;
19947 struct ast_config *ucfg;
19948 struct ast_variable *v;
19949 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
19950 const char *chans;
19951 const char *cat;
19952 int res;
19953
19954#ifdef HAVE_PRI
19955 char *c;
19956 int spanno;
19957 int i;
19958 int logicalspan;
19959 int trunkgroup;
19960 int dchannels[SIG_PRI_NUM_DCHANS];
19961#endif
19962 int have_cfg_now;
19963 static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
19964
19965 cfg = ast_config_load(config, config_flags);
19966 have_cfg_now = !!cfg;
19967 if (!cfg) {
19968 /* Error if we have no config file */
19969 if (had_cfg_before) {
19970 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
19972 }
19973 cfg = ast_config_new();/* Dummy config */
19974 if (!cfg) {
19975 return 0;
19976 }
19977 ucfg = ast_config_load("users.conf", config_flags);
19978 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
19979 ast_config_destroy(cfg);
19980 return 0;
19981 }
19982 if (ucfg == CONFIG_STATUS_FILEINVALID) {
19983 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
19984 ast_config_destroy(cfg);
19985 return 0;
19986 }
19987 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
19988 ucfg = ast_config_load("users.conf", config_flags);
19989 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
19990 return 0;
19991 }
19992 if (ucfg == CONFIG_STATUS_FILEINVALID) {
19993 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
19994 return 0;
19995 }
19997 cfg = ast_config_load(config, config_flags);
19998 have_cfg_now = !!cfg;
19999 if (!cfg) {
20000 if (had_cfg_before) {
20001 /* We should have been able to load the config. */
20002 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
20003 ast_config_destroy(ucfg);
20004 return 0;
20005 }
20006 cfg = ast_config_new();/* Dummy config */
20007 if (!cfg) {
20008 ast_config_destroy(ucfg);
20009 return 0;
20010 }
20011 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
20012 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
20013 ast_config_destroy(ucfg);
20014 return 0;
20015 }
20016 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
20017 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
20018 return 0;
20019 } else {
20021 ucfg = ast_config_load("users.conf", config_flags);
20022 if (ucfg == CONFIG_STATUS_FILEINVALID) {
20023 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
20024 ast_config_destroy(cfg);
20025 return 0;
20026 }
20027 }
20028 had_cfg_before = have_cfg_now;
20029
20030 /* It's a little silly to lock it, but we might as well just to be sure */
20032#ifdef HAVE_PRI
20033 if (reload != 1) {
20034 /* Process trunkgroups first */
20035 v = ast_variable_browse(cfg, "trunkgroups");
20036 while (v) {
20037 if (!strcasecmp(v->name, "trunkgroup")) {
20038 trunkgroup = atoi(v->value);
20039 if (trunkgroup > 0) {
20040 if ((c = strchr(v->value, ','))) {
20041 i = 0;
20042 memset(dchannels, 0, sizeof(dchannels));
20043 while (c && (i < SIG_PRI_NUM_DCHANS)) {
20044 dchannels[i] = atoi(c + 1);
20045 if (dchannels[i] < 0) {
20046 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);
20047 } else
20048 i++;
20049 c = strchr(c + 1, ',');
20050 }
20051 if (i) {
20052 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
20053 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);
20054 } else
20055 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");
20056 } else
20057 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
20058 } else
20059 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
20060 } else
20061 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
20062 } else if (!strcasecmp(v->name, "spanmap")) {
20063 spanno = atoi(v->value);
20064 if (spanno > 0) {
20065 if ((c = strchr(v->value, ','))) {
20066 trunkgroup = atoi(c + 1);
20067 if (trunkgroup > 0) {
20068 if ((c = strchr(c + 1, ',')))
20069 logicalspan = atoi(c + 1);
20070 else
20071 logicalspan = 0;
20072 if (logicalspan >= 0) {
20073 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
20074 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
20075 } else
20076 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
20077 } else
20078 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);
20079 } else
20080 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
20081 } else
20082 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
20083 } else
20084 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
20085 } else {
20086 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
20087 }
20088 v = v->next;
20089 }
20090 }
20091#endif
20092
20093 /* Copy the default jb config over global_jbconf */
20094 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
20095
20096 mwimonitornotify[0] = '\0';
20097
20098 v = ast_variable_browse(cfg, "channels");
20099 if ((res = process_dahdi(base_conf,
20100 "" /* Must be empty for the channels category. Silly voicemail mailbox. */,
20101 v, reload, 0))) {
20103 ast_config_destroy(cfg);
20104 if (ucfg) {
20105 ast_config_destroy(ucfg);
20106 }
20107 return res;
20108 }
20109
20110 /* Now get configuration from all normal sections in chan_dahdi.conf: */
20111 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
20112 /* [channels] and [trunkgroups] are used. Let's also reserve
20113 * [globals] and [general] for future use
20114 */
20115 if (!strcasecmp(cat, "general") ||
20116 !strcasecmp(cat, "trunkgroups") ||
20117 !strcasecmp(cat, "globals") ||
20118 !strcasecmp(cat, "channels")) {
20119 continue;
20120 }
20121
20122 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
20123 if (ast_strlen_zero(chans)) {
20124 /* Section is useless without a dahdichan value present. */
20125 continue;
20126 }
20127
20128 /* Copy base_conf to conf. */
20129 deep_copy_dahdi_chan_conf(conf, base_conf);
20130
20131 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
20133 ast_config_destroy(cfg);
20134 if (ucfg) {
20135 ast_config_destroy(ucfg);
20136 }
20137 return res;
20138 }
20139 }
20140
20141 ast_config_destroy(cfg);
20142
20143 if (ucfg) {
20144 /* Reset base_conf, so things don't leak from chan_dahdi.conf */
20145 deep_copy_dahdi_chan_conf(base_conf, default_conf);
20146 process_dahdi(base_conf,
20147 "" /* Must be empty for the general category. Silly voicemail mailbox. */,
20148 ast_variable_browse(ucfg, "general"), 1, 0);
20149
20150 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
20151 if (!strcasecmp(cat, "general")) {
20152 continue;
20153 }
20154
20155 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
20156 if (ast_strlen_zero(chans)) {
20157 /* Section is useless without a dahdichan value present. */
20158 continue;
20159 }
20160
20161 /* Copy base_conf to conf. */
20162 deep_copy_dahdi_chan_conf(conf, base_conf);
20163
20165 ast_config_destroy(ucfg);
20167 return res;
20168 }
20169 }
20170 ast_config_destroy(ucfg);
20171 }
20173
20174#ifdef HAVE_PRI
20175 if (reload != 1) {
20176 int x;
20177 for (x = 0; x < NUM_SPANS; x++) {
20178 if (pris[x].pri.pvts[0] &&
20179 pris[x].pri.master == AST_PTHREADT_NULL) {
20180 prepare_pri(pris + x);
20181 if (sig_pri_start_pri(&pris[x].pri)) {
20182 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
20183 return -1;
20184 } else
20185 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
20186 }
20187 }
20188 }
20189#endif
20190#if defined(HAVE_SS7)
20191 if (reload != 1) {
20192 int x;
20193 for (x = 0; x < NUM_SPANS; x++) {
20194 if (linksets[x].ss7.ss7) {
20195 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
20196 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
20197 return -1;
20198 } else
20199 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
20200 }
20201 }
20202 }
20203#endif /* defined(HAVE_SS7) */
20204#ifdef HAVE_OPENR2
20205 if (reload != 1) {
20206 struct r2link_entry *cur;
20207 int x = 0;
20208 AST_LIST_LOCK(&r2links);
20209 AST_LIST_TRAVERSE(&r2links, cur, list) {
20210 struct dahdi_mfcr2 *r2 = &cur->mfcr2;
20211 if (r2->r2master == AST_PTHREADT_NULL) {
20212 if (ast_pthread_create(&r2->r2master, NULL, mfcr2_monitor, r2)) {
20213 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
20214 return -1;
20215 } else {
20216 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
20217 }
20218 x++;
20219 }
20220 }
20221 AST_LIST_UNLOCK(&r2links);
20222 }
20223#endif
20224 /* And start the monitor for the first time */
20226 return 0;
20227}
static struct chans chans
static struct ast_jb_conf default_jbconf
Definition: chan_dahdi.c:618
static const char config[]
Definition: chan_dahdi.c:669
static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
Definition: chan_dahdi.c:18459
static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
Definition: chan_dahdi.c:19922
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3274
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:783
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
@ CONFIG_FLAG_FILEUNCHANGED
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
int sig_pri_start_pri(struct sig_pri_span *pri)
void * ss7_linkset(void *data)
Structure used to handle boolean flags.
Definition: utils.h:199
Definition: astman.c:88
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:584

References ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_config_new(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create, AST_PTHREADT_NULL, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, c, chans, config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, deep_copy_dahdi_chan_conf(), default_jbconf, global_jbconf, iflock, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sig_pri_span::master, sig_ss7_linkset::master, mwimonitornotify, ast_variable::name, ast_variable::next, NULL, NUM_SPANS, sig_pri_chan::pri, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_dahdi(), sig_pri_span::pvts, reload(), restart_monitor(), SIG_PRI_NUM_DCHANS, sig_pri_start_pri(), sig_ss7_linkset::ss7, ss7_linkset(), and ast_variable::value.

Referenced by dahdi_create_channel_range(), and setup_dahdi().

◆ sigtype_to_signalling()

static int sigtype_to_signalling ( int  sigtype)
static

Definition at line 12462 of file chan_dahdi.c.

12463{
12464 return sigtype;
12465}
enum analog_sigtype sigtype
Definition: sig_analog.c:69

References sigtype.

Referenced by mkintf().

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL()

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( dahdichannel_type  ,
to_ami = dahdichannel_to_ami 
)

◆ swap_subs()

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

Definition at line 4306 of file chan_dahdi.c.

4307{
4308 int tchan;
4309 int tinthreeway;
4310 struct ast_channel *towner;
4311
4312 ast_debug(1, "Swapping %d and %d\n", a, b);
4313
4314 tchan = p->subs[a].chan;
4315 towner = p->subs[a].owner;
4316 tinthreeway = p->subs[a].inthreeway;
4317
4318 p->subs[a].chan = p->subs[b].chan;
4319 p->subs[a].owner = p->subs[b].owner;
4320 p->subs[a].inthreeway = p->subs[b].inthreeway;
4321
4322 p->subs[b].chan = tchan;
4323 p->subs[b].owner = towner;
4324 p->subs[b].inthreeway = tinthreeway;
4325
4326 if (p->subs[a].owner)
4327 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
4328 if (p->subs[b].owner)
4329 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
4330 wakeup_sub(p, a);
4331 wakeup_sub(p, b);
4332}

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

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

◆ unalloc_sub()

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

Definition at line 4452 of file chan_dahdi.c.

4453{
4454 if (!x) {
4455 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
4456 return -1;
4457 }
4458 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
4459 dahdi_close_sub(p, x);
4460 p->subs[x].linear = 0;
4461 p->subs[x].chan = 0;
4462 p->subs[x].owner = NULL;
4463 p->subs[x].inthreeway = 0;
4465 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
4466 return 0;
4467}

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, NULL, dahdi_subchannel::owner, dahdi_pvt::polarity, POLARITY_IDLE, and dahdi_pvt::subs.

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

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 18210 of file chan_dahdi.c.

18211{
18212#if defined(HAVE_PRI) || defined(HAVE_SS7)
18213 int y;
18214#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18215#ifdef HAVE_PRI
18216 for (y = 0; y < NUM_SPANS; y++)
18217 ast_mutex_destroy(&pris[y].pri.lock);
18218#endif
18219#if defined(HAVE_SS7)
18220 for (y = 0; y < NUM_SPANS; y++)
18221 ast_mutex_destroy(&linksets[y].ss7.lock);
18222#endif /* defined(HAVE_SS7) */
18223 return __unload_module();
18224}

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

◆ wakeup_sub()

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

Definition at line 3728 of file chan_dahdi.c.

3729{
3731 if (p->subs[a].owner) {
3734 }
3735}
static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
Definition: chan_dahdi.c:3712

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

Variable Documentation

◆ __mod_info

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, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .requires = "ccss", .optional_modules = "res_smdi", }
static

Definition at line 20521 of file chan_dahdi.c.

◆ alarm

int alarm

Definition at line 4608 of file chan_dahdi.c.

Referenced by alarm2str().

◆ 

struct { ... } alarms[]

Referenced by alarm2str().

◆ analog_callbacks

struct analog_callback analog_callbacks

Global analog callbacks to the upper layer.

Definition at line 3604 of file chan_dahdi.c.

Referenced by analog_all_subchannels_hungup(), analog_alloc_sub(), analog_answer_polarityswitch(), analog_callwait(), analog_cancel_cidspill(), analog_cb_handle_dtmf(), analog_check_confirmanswer(), analog_check_for_conference(), analog_check_waitingfordt(), analog_confmute(), analog_deadlock_avoidance_private(), analog_decrease_ss_count(), analog_dial_digits(), analog_distinctive_ring(), analog_dsp_reset_and_flush_digits(), analog_dsp_set_digitmode(), analog_flash(), analog_get_and_handle_alarms(), analog_get_bridged_channel(), analog_get_callerid(), analog_get_event(), analog_get_orig_dialstring(), analog_get_sub_fd(), analog_handle_notify_message(), analog_hangup_polarityswitch(), analog_has_voicemail(), analog_have_progressdetect(), analog_increase_ss_count(), analog_is_dialing(), analog_is_off_hook(), analog_lock_private(), analog_new_ast_channel(), analog_off_hook(), analog_on_hook(), analog_play_tone(), analog_ring(), analog_send_callerid(), analog_set_alarm(), analog_set_cadence(), analog_set_callwaiting(), analog_set_confirmanswer(), analog_set_dialing(), analog_set_echocanceller(), analog_set_inthreeway(), analog_set_linear_mode(), analog_set_needringing(), analog_set_new_owner(), analog_set_outgoing(), analog_set_pulsedial(), analog_set_ringtimeout(), analog_set_waitingfordt(), analog_start(), analog_start_cid_detect(), analog_start_polarityswitch(), analog_stop_callwait(), analog_stop_cid_detect(), analog_swap_subs(), analog_train_echocanceller(), analog_unalloc_sub(), analog_unlock_private(), analog_update_conf(), analog_wait_event(), and analog_wink().

◆ AS_RP_cadence

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

Definition at line 709 of file chan_dahdi.c.

Referenced by mwi_send_process_buffer().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 20521 of file chan_dahdi.c.

◆ cadences

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
static

◆ cidrings

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

Referenced by handle_dahdi_show_cadences(), my_set_cadence(), and process_dahdi().

◆ config

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

Definition at line 669 of file chan_dahdi.c.

Referenced by setup_dahdi_int().

◆ dahdi_cli

struct ast_cli_entry dahdi_cli[]
static

Definition at line 16709 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

◆ dahdi_tech

struct ast_channel_tech dahdi_tech
static

◆ default_jbconf

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

Referenced by setup_dahdi_int().

◆ defaultcic

char defaultcic[64] = ""
static

Definition at line 717 of file chan_dahdi.c.

Referenced by process_dahdi().

◆ defaultozz

char defaultozz[64] = ""
static

Definition at line 718 of file chan_dahdi.c.

Referenced by process_dahdi().

◆ distinctiveringaftercid

int distinctiveringaftercid = 0
static

Definition at line 729 of file chan_dahdi.c.

Referenced by analog_ss_thread(), my_distinctive_ring(), and process_dahdi().

◆ dtmfcid_level

int dtmfcid_level = 256
static

Definition at line 734 of file chan_dahdi.c.

Referenced by do_monitor(), and process_dahdi().

◆ events

const char* const events[]
static

Definition at line 4585 of file chan_dahdi.c.

Referenced by event2str().

◆ global_jbconf

struct ast_jb_conf global_jbconf
static

Definition at line 626 of file chan_dahdi.c.

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

◆ has_pseudo

int has_pseudo
static

Definition at line 688 of file chan_dahdi.c.

Referenced by build_channels(), and process_dahdi().

◆ ifcount

int ifcount = 0
static

Definition at line 749 of file chan_dahdi.c.

Referenced by destroy_all_channels(), do_monitor(), and mkintf().

◆ ifend

struct dahdi_pvt* ifend = NULL
static

Main interface list end

Definition at line 923 of file chan_dahdi.c.

Referenced by dahdi_cc_callback(), dahdi_iflist_extract(), dahdi_iflist_insert(), dahdi_request(), and determine_starting_point().

◆ iflist

struct dahdi_pvt* iflist = NULL
static

◆ iflock

ast_mutex_t iflock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

◆ lbostr

const char* const lbostr[]
static

Definition at line 605 of file chan_dahdi.c.

Referenced by action_dahdishowstatus(), and dahdi_show_status().

◆ monitor_thread

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

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

◆ monlock

ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
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 757 of file chan_dahdi.c.

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

◆ mwilevel

int mwilevel = 512
static

Definition at line 733 of file chan_dahdi.c.

Referenced by do_monitor(), mwi_thread(), and process_dahdi().

◆ mwimonitornotify

char mwimonitornotify[PATH_MAX] = ""
static

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

Definition at line 721 of file chan_dahdi.c.

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

◆ mwisend_rpas

int mwisend_rpas = 0
static

Definition at line 723 of file chan_dahdi.c.

Referenced by mwi_send_init(), and process_dahdi().

◆ name

char* name

◆ num_cadence

int num_cadence = 4
static

Definition at line 685 of file chan_dahdi.c.

Referenced by handle_dahdi_show_cadences(), my_set_cadence(), and process_dahdi().

◆ num_restart_pending

int num_restart_pending = 0
static

◆ numbufs

int numbufs = 4
static

Definition at line 731 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default(), and process_dahdi().

◆ polarity_function

struct ast_custom_function polarity_function
static
Initial value:
= {
.name = "POLARITY",
.write = polarity_write,
.read = polarity_read,
}
static int polarity_read(struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)
Definition: chan_dahdi.c:2862
static int polarity_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: chan_dahdi.c:2876

Definition at line 2903 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

◆ progzone

char progzone[10] = ""
static

Definition at line 726 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

◆ report_alarms

int report_alarms = REPORT_CHANNEL_ALARMS
static

Definition at line 738 of file chan_dahdi.c.

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

◆ restart_lock

ast_mutex_t restart_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 764 of file chan_dahdi.c.

Referenced by dahdi_restart().

◆ ringt_base

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

Referenced by mkintf(), and process_dahdi().

◆ round_robin

struct dahdi_pvt* round_robin[64]
static

Round robin search locations.

Definition at line 3678 of file chan_dahdi.c.

Referenced by dahdi_request(), dahdi_restart(), determine_starting_point(), and load_module().

◆ ss_thread_complete

ast_cond_t ss_thread_complete
static

◆ ss_thread_count

int ss_thread_count = 0
static

◆ ss_thread_lock

ast_mutex_t ss_thread_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

◆ subnames

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

Definition at line 916 of file chan_dahdi.c.

Referenced by alloc_sub(), dahdi_new(), and native_start().

◆ tdesc

const char tdesc[] = "DAHDI Telephony"
static

Definition at line 648 of file chan_dahdi.c.

◆ usedistinctiveringdetection

int usedistinctiveringdetection = 0
static

Definition at line 728 of file chan_dahdi.c.

Referenced by mkintf(), and process_dahdi().

◆ user_has_defined_cadences

int user_has_defined_cadences = 0
static

Definition at line 686 of file chan_dahdi.c.

Referenced by process_dahdi().