Asterisk - The Open Source Telephony Project GIT-master-c753fe4
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 712 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX

#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)

Definition at line 752 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX_INCOMING

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 751 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX_OUTGOING

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 750 of file chan_dahdi.c.

◆ CALLPROGRESS_PROGRESS

#define CALLPROGRESS_PROGRESS   1

Definition at line 749 of file chan_dahdi.c.

◆ CALLWAITING_REPEAT_SAMPLES

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

10,000 ms

Definition at line 870 of file chan_dahdi.c.

◆ CALLWAITING_SILENT_SAMPLES

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

300 ms

Definition at line 869 of file chan_dahdi.c.

◆ CALLWAITING_SUPPRESS_SAMPLES

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

100 ms

Definition at line 871 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 784 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 785 of file chan_dahdi.c.

◆ CHAN_PSEUDO

#define CHAN_PSEUDO   -2

Definition at line 747 of file chan_dahdi.c.

◆ CIDCW_EXPIRE_SAMPLES

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

500 ms

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

◆ DEFAULT_DIALTONE_DETECT_TIMEOUT

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

10,000 ms

Definition at line 875 of file chan_dahdi.c.

◆ DEFAULT_RINGT

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

8,000 ms

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

◆ GET_CHANNEL

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

Definition at line 1250 of file chan_dahdi.c.

◆ HANGUP

#define HANGUP   1

Definition at line 16839 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:792
#define SIG_FXSKS
Definition: chan_dahdi.h:794
#define SIG_FXSGS
Definition: chan_dahdi.h:793
#define SIG_PRI
Definition: chan_dahdi.h:806

Definition at line 781 of file chan_dahdi.c.

◆ MASK_AVAIL

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 866 of file chan_dahdi.c.

◆ MASK_INUSE

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

◆ MIN_MS_SINCE_FLASH

#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

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

◆ NUM_CADENCE_MAX

#define NUM_CADENCE_MAX   25

Definition at line 754 of file chan_dahdi.c.

◆ NUM_SPANS

#define NUM_SPANS   32

Definition at line 744 of file chan_dahdi.c.

◆ POLARITY_IDLE

#define POLARITY_IDLE   0

Definition at line 983 of file chan_dahdi.c.

◆ POLARITY_REV

#define POLARITY_REV   1

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

◆ PROC_DAHDI_OPT_NOWARN

#define PROC_DAHDI_OPT_NOWARN   (1 << 1)

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

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

◆ REPORT_CHANNEL_ALARMS

#define REPORT_CHANNEL_ALARMS   1

Definition at line 806 of file chan_dahdi.c.

◆ REPORT_SPAN_ALARMS

#define REPORT_SPAN_ALARMS   2

Definition at line 807 of file chan_dahdi.c.

◆ sig2str

#define sig2str   dahdi_sig2str

Definition at line 4785 of file chan_dahdi.c.

◆ SMDI_MD_WAIT_TIMEOUT

#define SMDI_MD_WAIT_TIMEOUT   1500 /* 1.5 seconds */

Definition at line 673 of file chan_dahdi.c.

◆ TRAILER_MS

#define TRAILER_MS   5

◆ TRANSFER

#define TRANSFER   0

Definition at line 16838 of file chan_dahdi.c.

Function Documentation

◆ __dahdi_exception()

static struct ast_frame * __dahdi_exception ( struct ast_channel ast)
static

Definition at line 8721 of file chan_dahdi.c.

8722{
8723 int res;
8724 int idx;
8725 struct ast_frame *f;
8726 int usedindex = -1;
8727 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8728
8729 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
8730 idx = SUB_REAL;
8731 }
8732
8733 p->subs[idx].f.frametype = AST_FRAME_NULL;
8734 p->subs[idx].f.datalen = 0;
8735 p->subs[idx].f.samples = 0;
8736 p->subs[idx].f.mallocd = 0;
8737 p->subs[idx].f.offset = 0;
8738 p->subs[idx].f.subclass.integer = 0;
8739 p->subs[idx].f.delivery = ast_tv(0,0);
8740 p->subs[idx].f.src = "dahdi_exception";
8741 p->subs[idx].f.data.ptr = NULL;
8742
8743
8744 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
8745 /* If nobody owns us, absorb the event appropriately, otherwise
8746 we loop indefinitely. This occurs when, during call waiting, the
8747 other end hangs up our channel so that it no longer exists, but we
8748 have neither FLASH'd nor ONHOOK'd to signify our desire to
8749 change to the other channel. */
8750 if (p->fake_event) {
8751 res = p->fake_event;
8752 p->fake_event = 0;
8753 } else
8754 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
8755 /* Switch to real if there is one and this isn't something really silly... */
8756 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
8757 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
8758 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
8759 p->owner = p->subs[SUB_REAL].owner;
8760 if (p->owner) {
8762 }
8763 p->subs[SUB_REAL].needunhold = 1;
8764 }
8765 switch (res) {
8766 case DAHDI_EVENT_ONHOOK:
8768 if (p->owner) {
8769 ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
8771 p->callwaitingrepeat = 0;
8772 p->cidcwexpire = 0;
8773 p->cid_suppress_expire = 0;
8774 } else
8775 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8777 break;
8778 case DAHDI_EVENT_RINGOFFHOOK:
8779 dahdi_ec_enable(p);
8780 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
8781 if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
8782 p->subs[SUB_REAL].needanswer = 1;
8783 p->dialing = 0;
8784 }
8785 break;
8786 case DAHDI_EVENT_HOOKCOMPLETE:
8787 case DAHDI_EVENT_RINGERON:
8788 case DAHDI_EVENT_RINGEROFF:
8789 /* Do nothing */
8790 break;
8791 case DAHDI_EVENT_WINKFLASH:
8792 p->flashtime = ast_tvnow();
8793 if (p->owner) {
8794 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
8796 /* Answer if necessary */
8797 usedindex = dahdi_get_index(p->owner, p, 0);
8798 if (usedindex > -1) {
8799 p->subs[usedindex].needanswer = 1;
8800 }
8802 }
8803 p->callwaitingrepeat = 0;
8804 p->cidcwexpire = 0;
8805 p->cid_suppress_expire = 0;
8807 p->subs[SUB_REAL].needunhold = 1;
8808 } else
8809 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8811 break;
8812 default:
8813 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
8814 }
8815 f = &p->subs[idx].f;
8816 return f;
8817 }
8818 if (!(p->radio || (p->oprmode < 0)))
8819 ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
8820 /* If it's not us, return NULL immediately */
8821 if (ast != p->owner) {
8822 if (p->owner) {
8823 ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
8824 }
8825 f = &p->subs[idx].f;
8826 return f;
8827 }
8828
8829 f = dahdi_handle_event(ast);
8830 if (!f) {
8831 const char *name = ast_strdupa(ast_channel_name(ast));
8832
8833 /* Tell the CDR this DAHDI device hung up */
8835 ast_channel_unlock(ast);
8836 ast_set_hangupsource(ast, name, 0);
8837 ast_channel_lock(ast);
8838 ast_mutex_lock(&p->lock);
8839 }
8840 return f;
8841}
#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:7534
char * name
Definition: chan_dahdi.c:4691
static int dahdi_set_hook(int fd, int hs)
Definition: chan_dahdi.c:5252
void dahdi_ec_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4968
void dahdi_conf_update(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4913
static struct ast_frame * dahdi_handle_event(struct ast_channel *ast)
Definition: chan_dahdi.c:7819
static const char * event2str(int event)
Definition: chan_dahdi.c:4712
void dahdi_ec_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5040
static int dahdi_get_event(int fd)
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition: chan_dahdi.c:843
#define SUB_REAL
Definition: chan_dahdi.h:57
#define dahdi_get_index(ast, p, nullok)
Definition: chan_dahdi.h:888
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:2972
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:2468
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1254
#define ast_channel_unlock(chan)
Definition: channel.h:2973
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:7359
@ 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:197
#define ast_mutex_lock(a)
Definition: lock.h:196
#define NULL
Definition: resample.c:96
Data structure associated with a single frame of data.
union ast_frame::@228 data
struct ast_frame_subclass subclass
struct timeval delivery
enum ast_frame_type frametype
const char * src
int cid_suppress_expire
Definition: chan_dahdi.h:601
struct timeval flashtime
Definition: chan_dahdi.h:698
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:728
int radio
Nonzero if the signaling type is sent over a radio.
Definition: chan_dahdi.h:148
int cidcwexpire
Definition: chan_dahdi.h:600
int callwaitingrepeat
Definition: chan_dahdi.h:599
ast_mutex_t lock
Definition: chan_dahdi.h:125
int channel
Definition: chan_dahdi.h:591
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 20639 of file chan_dahdi.c.

◆ __unload_module()

static int __unload_module ( void  )
static

Definition at line 18210 of file chan_dahdi.c.

18211{
18212 struct dahdi_pvt *p;
18213#if defined(HAVE_PRI) || defined(HAVE_SS7)
18214 int i, j;
18215#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18216
18217#ifdef HAVE_PRI
18218 for (i = 0; i < NUM_SPANS; i++) {
18219 if (pris[i].pri.master != AST_PTHREADT_NULL) {
18220 pthread_cancel(pris[i].pri.master);
18221 pthread_kill(pris[i].pri.master, SIGURG);
18222 }
18223 }
18224 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18225 ast_unregister_application(dahdi_send_keypad_facility_app);
18226#ifdef HAVE_PRI_PROG_W_CAUSE
18227 ast_unregister_application(dahdi_send_callrerouting_facility_app);
18228#endif
18229#endif
18230#if defined(HAVE_SS7)
18231 for (i = 0; i < NUM_SPANS; i++) {
18232 if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
18233 pthread_cancel(linksets[i].ss7.master);
18234 pthread_kill(linksets[i].ss7.master, SIGURG);
18235 }
18236 }
18237 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18238#endif /* defined(HAVE_SS7) */
18239#if defined(HAVE_OPENR2)
18240 dahdi_r2_destroy_links();
18241 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18242 ast_unregister_application(dahdi_accept_r2_call_app);
18243#endif
18244
18246
18248 ast_manager_unregister("DAHDIDialOffhook");
18249 ast_manager_unregister("DAHDIHangup");
18250 ast_manager_unregister("DAHDITransfer");
18251 ast_manager_unregister("DAHDIDNDoff");
18252 ast_manager_unregister("DAHDIDNDon");
18253 ast_manager_unregister("DAHDIShowChannels");
18254 ast_manager_unregister("DAHDIShowStatus");
18255 ast_manager_unregister("DAHDIRestart");
18256#if defined(HAVE_PRI)
18257 ast_manager_unregister("PRIShowSpans");
18258 ast_manager_unregister("PRIDebugSet");
18259 ast_manager_unregister("PRIDebugFileSet");
18260 ast_manager_unregister("PRIDebugFileUnset");
18261#endif /* defined(HAVE_PRI) */
18263
18264 /* Hangup all interfaces if they have an owner */
18266 for (p = iflist; p; p = p->next) {
18267 if (p->owner)
18269 }
18271
18274 pthread_cancel(monitor_thread);
18275 pthread_kill(monitor_thread, SIGURG);
18276 pthread_join(monitor_thread, NULL);
18277 }
18280
18282
18283#if defined(HAVE_PRI)
18284 for (i = 0; i < NUM_SPANS; i++) {
18285 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
18286 pthread_join(pris[i].pri.master, NULL);
18287 }
18288 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
18289 dahdi_close_pri_fd(&(pris[i]), j);
18290 }
18291 sig_pri_stop_pri(&pris[i].pri);
18292 }
18293#if defined(HAVE_PRI_CCSS)
18294 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
18295 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
18296#endif /* defined(HAVE_PRI_CCSS) */
18298#endif
18299
18300#if defined(HAVE_SS7)
18301 for (i = 0; i < NUM_SPANS; i++) {
18302 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
18303 pthread_join(linksets[i].ss7.master, NULL);
18304 }
18305 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
18306 dahdi_close_ss7_fd(&(linksets[i]), j);
18307 }
18308 if (linksets[i].ss7.ss7) {
18309 ss7_destroy(linksets[i].ss7.ss7);
18310 linksets[i].ss7.ss7 = NULL;
18311 }
18312 }
18313#endif /* defined(HAVE_SS7) */
18315
18317
18320 STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
18321 return 0;
18322}
#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:1201
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition: ccss.c:1238
static ast_mutex_t iflock
Protect the interface list (of dahdi_pvt's)
Definition: chan_dahdi.c:816
#define NUM_SPANS
Definition: chan_dahdi.c:744
static struct dahdi_pvt * iflist
Definition: chan_dahdi.c:992
static ast_cond_t ss_thread_complete
Definition: chan_dahdi.c:832
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:827
static struct ast_channel_tech dahdi_tech
Definition: chan_dahdi.c:1227
static struct ast_custom_function polarity_function
Definition: chan_dahdi.c:2985
static struct ast_cli_entry dahdi_cli[]
Definition: chan_dahdi.c:16823
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:831
static void destroy_all_channels(void)
Definition: chan_dahdi.c:5995
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:569
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2440
@ AST_SOFTHANGUP_APPUNLOAD
Definition: channel.h:1163
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:7699
#define ast_cond_destroy(cond)
Definition: lock.h:209
#define AST_PTHREADT_NULL
Definition: lock.h:73
#define AST_PTHREADT_STOP
Definition: lock.h:74
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:652
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 20639 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 3762 of file chan_dahdi.c.

3763{
3764 int res;
3765 if (p->subs[SUB_REAL].owner == ast)
3766 res = 0;
3767 else if (p->subs[SUB_CALLWAIT].owner == ast)
3768 res = 1;
3769 else if (p->subs[SUB_THREEWAY].owner == ast)
3770 res = 2;
3771 else {
3772 res = -1;
3773 if (!nullok)
3775 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
3776 ast ? ast_channel_name(ast) : "", p->channel, fname, line);
3777 }
3778 return res;
3779}
#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 16976 of file chan_dahdi.c.

16977{
16978 struct dahdi_pvt *p;
16979 const char *channel = astman_get_header(m, "DAHDIChannel");
16980 const char *number = astman_get_header(m, "Number");
16981 int i;
16982
16983 if (ast_strlen_zero(channel)) {
16984 astman_send_error(s, m, "No channel specified");
16985 return 0;
16986 }
16987 if (ast_strlen_zero(number)) {
16988 astman_send_error(s, m, "No number specified");
16989 return 0;
16990 }
16992 if (!p) {
16993 astman_send_error(s, m, "No such channel");
16994 return 0;
16995 }
16996 if (!p->owner) {
16997 astman_send_error(s, m, "Channel does not have it's owner");
16998 return 0;
16999 }
17000 for (i = 0; i < strlen(number); i++) {
17001 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
17002 dahdi_queue_frame(p, &f);
17003 }
17004 astman_send_ack(s, m, "DAHDIDialOffhook");
17005 return 0;
17006}
static struct dahdi_pvt * find_channel_from_str(const char *channel)
Definition: chan_dahdi.c:16880
static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
Definition: chan_dahdi.c:3819
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1986
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2018
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1647
#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:157

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

16912{
16913 struct dahdi_pvt *p;
16914 const char *channel = astman_get_header(m, "DAHDIChannel");
16915
16916 if (ast_strlen_zero(channel)) {
16917 astman_send_error(s, m, "No channel specified");
16918 return 0;
16919 }
16921 if (!p) {
16922 astman_send_error(s, m, "No such channel");
16923 return 0;
16924 }
16925 dahdi_dnd(p, 0);
16926 astman_send_ack(s, m, "DND Disabled");
16927 return 0;
16928}
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:9936

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

16893{
16894 struct dahdi_pvt *p;
16895 const char *channel = astman_get_header(m, "DAHDIChannel");
16896
16897 if (ast_strlen_zero(channel)) {
16898 astman_send_error(s, m, "No channel specified");
16899 return 0;
16900 }
16902 if (!p) {
16903 astman_send_error(s, m, "No such channel");
16904 return 0;
16905 }
16906 dahdi_dnd(p, 1);
16907 astman_send_ack(s, m, "DND Enabled");
16908 return 0;
16909}

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

16082{
16083 if (dahdi_restart() != 0) {
16084 astman_send_error(s, m, "Failed rereading DAHDI configuration");
16085 return 1;
16086 }
16087 astman_send_ack(s, m, "DAHDIRestart: Success");
16088 return 0;
16089}
static int dahdi_restart(void)
Definition: chan_dahdi.c:15943

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

17009{
17010 struct dahdi_pvt *tmp = NULL;
17011 const char *id = astman_get_header(m, "ActionID");
17012 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
17013 char idText[256];
17014 int channels = 0;
17015 int dahdichanquery;
17016
17017 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
17018 /* Not numeric string. */
17019 dahdichanquery = -1;
17020 }
17021
17022 idText[0] = '\0';
17023 if (!ast_strlen_zero(id)) {
17024 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
17025 }
17026
17027 astman_send_listack(s, m, "DAHDI channel status will follow", "start");
17028
17030
17031 for (tmp = iflist; tmp; tmp = tmp->next) {
17032 if (tmp->channel > 0) {
17033 int alm;
17034
17035 /* If a specific channel is queried for, only deliver status for that channel */
17036 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
17037 continue;
17038
17039 alm = get_alarms(tmp);
17040 channels++;
17041 if (tmp->owner) {
17042 /* Add data if we have a current call */
17043 astman_append(s,
17044 "Event: DAHDIShowChannels\r\n"
17045 "DAHDIChannel: %d\r\n"
17046 "Channel: %s\r\n"
17047 "Uniqueid: %s\r\n"
17048 "AccountCode: %s\r\n"
17049 "Signalling: %s\r\n"
17050 "SignallingCode: %d\r\n"
17051 "Context: %s\r\n"
17052 "DND: %s\r\n"
17053 "Alarm: %s\r\n"
17054 "Description: %s\r\n"
17055 "%s"
17056 "\r\n",
17057 tmp->channel,
17058 ast_channel_name(tmp->owner),
17061 sig2str(tmp->sig),
17062 tmp->sig,
17063 tmp->context,
17064 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
17065 alarm2str(alm),
17066 tmp->description, idText);
17067 } else {
17068 astman_append(s,
17069 "Event: DAHDIShowChannels\r\n"
17070 "DAHDIChannel: %d\r\n"
17071 "Signalling: %s\r\n"
17072 "SignallingCode: %d\r\n"
17073 "Context: %s\r\n"
17074 "DND: %s\r\n"
17075 "Alarm: %s\r\n"
17076 "Description: %s\r\n"
17077 "%s"
17078 "\r\n",
17079 tmp->channel, sig2str(tmp->sig), tmp->sig,
17080 tmp->context,
17081 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
17082 alarm2str(alm),
17083 tmp->description, idText);
17084 }
17085 }
17086 }
17087
17089
17090 astman_send_list_complete_start(s, m, "DAHDIShowChannelsComplete", channels);
17091 astman_append(s, "Items: %d\r\n", channels);
17093 return 0;
17094}
static char * alarm2str(int alm)
Definition: chan_dahdi.c:4702
#define sig2str
Definition: chan_dahdi.c:4785
static int get_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7637
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:2028
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:2064
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2072
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1907
char description[32]
A description for the channel configuration.
Definition: chan_dahdi.h:502
char context[AST_MAX_CONTEXT]
The configured context for incoming calls.
Definition: chan_dahdi.h:497

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(), dahdi_pvt::channel, channels, dahdi_pvt::context, dahdi_dnd(), dahdi_pvt::description, get_alarms(), iflist, iflock, dahdi_pvt::next, NULL, dahdi_pvt::owner, dahdi_pvt::sig, and sig2str.

Referenced by load_module().

◆ action_dahdishowstatus()

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

Definition at line 17096 of file chan_dahdi.c.

17097{
17098 const char *id = astman_get_header(m, "ActionID");
17099 int span;
17100 int res;
17101 char alarmstr[50];
17102 int ctl;
17103 char idText[256];
17104 int numspans = 0;
17105 struct dahdi_spaninfo spaninfo;
17106
17107 ctl = open("/dev/dahdi/ctl", O_RDWR);
17108 if (ctl < 0) {
17109 astman_send_error(s, m, "No DAHDI detected");
17110 return 0;
17111 }
17112
17113 idText[0] = '\0';
17114 if (!ast_strlen_zero(id)) {
17115 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
17116 }
17117 astman_send_listack(s, m, "DAHDI span statuses will follow", "start");
17118
17119 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
17120 spaninfo.spanno = span;
17121 res = ioctl(ctl, DAHDI_SPANSTAT, &spaninfo);
17122 if (res) {
17123 continue;
17124 }
17125 numspans++;
17126 build_alarm_info(alarmstr, &spaninfo);
17127 astman_append(s,
17128 "Event: DAHDIShowStatus\r\n"
17129 "Span: %d\r\n"
17130 "Description: %s\r\n"
17131 "Alarms: %s\r\n"
17132 "IRQ: %d\r\n"
17133 "bpviol: %d\r\n"
17134 "CRC: %d\r\n"
17135 "Framing: %s\r\n"
17136 "Coding: %s\r\n"
17137 "Options: %s\r\n"
17138 "LBO: %s\r\n"
17139 "%s"
17140 "\r\n",
17141 span, spaninfo.desc, alarmstr, spaninfo.irqmisses, spaninfo.bpvcount, spaninfo.crc4count,
17142 spaninfo.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
17143 spaninfo.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
17144 spaninfo.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
17145 "CAS",
17146 spaninfo.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
17147 spaninfo.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
17148 spaninfo.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
17149 "Unk",
17150 spaninfo.lineconfig & DAHDI_CONFIG_CRC4 ?
17151 spaninfo.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
17152 spaninfo.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
17153 lbostr[spaninfo.lbo],
17154 idText);
17155 }
17156 close(ctl);
17157
17158 astman_send_list_complete_start(s, m, "DAHDIShowStatusComplete", numspans);
17159 astman_append(s, "Items: %d\r\n", numspans);
17161 return 0;
17162}
static void build_alarm_info(char *restrict alarmstr, struct dahdi_spaninfo *spaninfo)
Definition: chan_dahdi.c:16411
static const char *const lbostr[]
Definition: chan_dahdi.c:675

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

16931{
16932 struct dahdi_pvt *p;
16933 const char *channel = astman_get_header(m, "DAHDIChannel");
16934
16935 if (ast_strlen_zero(channel)) {
16936 astman_send_error(s, m, "No channel specified");
16937 return 0;
16938 }
16940 if (!p) {
16941 astman_send_error(s, m, "No such channel");
16942 return 0;
16943 }
16944 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16945 astman_send_error(s, m, "Channel signaling is not analog");
16946 return 0;
16947 }
16949 astman_send_ack(s, m, "DAHDITransfer");
16950 return 0;
16951}
#define TRANSFER
Definition: chan_dahdi.c:16838
static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
Definition: chan_dahdi.c:16841
static int dahdi_analog_lib_handles(int signalling, int radio, int oprmode)
Definition: chan_dahdi.h:847

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

16954{
16955 struct dahdi_pvt *p;
16956 const char *channel = astman_get_header(m, "DAHDIChannel");
16957
16958 if (ast_strlen_zero(channel)) {
16959 astman_send_error(s, m, "No channel specified");
16960 return 0;
16961 }
16963 if (!p) {
16964 astman_send_error(s, m, "No such channel");
16965 return 0;
16966 }
16967 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16968 astman_send_error(s, m, "Channel signaling is not analog");
16969 return 0;
16970 }
16972 astman_send_ack(s, m, "DAHDIHangup");
16973 return 0;
16974}
#define HANGUP
Definition: chan_dahdi.c:16839

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

4703{
4704 int x;
4705 for (x = 0; x < ARRAY_LEN(alarms); x++) {
4706 if (alarms[x].alarm & alm)
4707 return alarms[x].name;
4708 }
4709 return alm ? "Unknown Alarm" : "No Alarm";
4710}
int alarm
Definition: chan_dahdi.c:4690
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 4497 of file chan_dahdi.c.

4498{
4499 struct dahdi_bufferinfo bi;
4500 int res;
4501 if (p->subs[x].dfd >= 0) {
4502 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
4503 return -1;
4504 }
4505
4506 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
4507 if (p->subs[x].dfd <= -1) {
4508 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
4509 return -1;
4510 }
4511
4512 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
4513 if (!res) {
4514 bi.txbufpolicy = p->buf_policy;
4515 bi.rxbufpolicy = p->buf_policy;
4516 bi.numbufs = p->buf_no;
4517 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
4518 if (res < 0) {
4519 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
4520 }
4521 } else
4522 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
4523
4524 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
4525 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
4526 dahdi_close_sub(p, x);
4527 p->subs[x].dfd = -1;
4528 return -1;
4529 }
4530 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
4531 return 0;
4532}
static int dahdi_open(char *fn)
Definition: chan_dahdi.c:4416
static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
Definition: chan_dahdi.c:4469
const char *const subnames[]
Definition: chan_dahdi.c:986
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 9982 of file chan_dahdi.c.

9983{
9984 struct ast_channel *chan = data;
9985 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9986 char exten[AST_MAX_EXTENSION] = "";
9987 char exten2[AST_MAX_EXTENSION] = "";
9988 unsigned char buf[256];
9989 char dtmfcid[300];
9990 char dtmfbuf[300];
9991 struct callerid_state *cs = NULL;
9992 char *name = NULL, *number = NULL;
9993 int distMatches;
9994 int curRingData[3];
9995 int receivedRingT;
9996 int counter1;
9997 int counter;
9998 int samples = 0;
9999 struct ast_smdi_md_message *smdi_msg = NULL;
10000 int flags = 0;
10001 int i;
10002 int timeout;
10003 int getforward = 0;
10004 char *s1, *s2;
10005 int len = 0;
10006 int res;
10007 int idx;
10008 RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
10009 const char *pickupexten;
10010
10014 /* in the bizarre case where the channel has become a zombie before we
10015 even get started here, abort safely
10016 */
10017 if (!p) {
10018 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
10019 ast_hangup(chan);
10020 goto quit;
10021 }
10022 ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
10023 idx = dahdi_get_index(chan, p, 1);
10024 if (idx < 0) {
10025 ast_log(LOG_WARNING, "Huh?\n");
10026 ast_hangup(chan);
10027 goto quit;
10028 }
10029
10030 ast_channel_lock(chan);
10031 pickup_cfg = ast_get_chan_features_pickup_config(chan);
10032 if (!pickup_cfg) {
10033 ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
10034 pickupexten = "";
10035 } else {
10036 pickupexten = ast_strdupa(pickup_cfg->pickupexten);
10037 }
10038 ast_channel_unlock(chan);
10039
10040 if (p->dsp)
10042 switch (p->sig) {
10043 case SIG_FEATD:
10044 case SIG_FEATDMF:
10045 case SIG_FEATDMF_TA:
10046 case SIG_E911:
10047 case SIG_FGC_CAMAMF:
10048 case SIG_FEATB:
10049 case SIG_EMWINK:
10050 case SIG_SF_FEATD:
10051 case SIG_SF_FEATDMF:
10052 case SIG_SF_FEATB:
10053 case SIG_SFWINK:
10054 if (dahdi_wink(p, idx))
10055 goto quit;
10056 /* Fall through */
10057 case SIG_EM:
10058 case SIG_EM_E1:
10059 case SIG_SF:
10060 case SIG_FGC_CAMA:
10061 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10062 if (p->dsp)
10064 /* set digit mode appropriately */
10065 if (p->dsp) {
10066 if (NEED_MFDETECT(p))
10068 else
10070 }
10071 memset(dtmfbuf, 0, sizeof(dtmfbuf));
10072 /* Wait for the first digit only if immediate=no */
10073 if (!p->immediate)
10074 /* Wait for the first digit (up to 5 seconds). */
10075 res = ast_waitfordigit(chan, 5000);
10076 else
10077 res = 0;
10078 if (res > 0) {
10079 /* save first char */
10080 dtmfbuf[0] = res;
10081 switch (p->sig) {
10082 case SIG_FEATD:
10083 case SIG_SF_FEATD:
10084 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10085 if (res > 0)
10086 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10087 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10088 break;
10089 case SIG_FEATDMF_TA:
10090 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10091 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10092 if (dahdi_wink(p, idx)) goto quit;
10093 dtmfbuf[0] = 0;
10094 /* Wait for the first digit (up to 5 seconds). */
10095 res = ast_waitfordigit(chan, 5000);
10096 if (res <= 0) break;
10097 dtmfbuf[0] = res;
10098 /* fall through intentionally */
10099 case SIG_FEATDMF:
10100 case SIG_E911:
10101 case SIG_FGC_CAMAMF:
10102 case SIG_SF_FEATDMF:
10103 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10104 /* if international caca, do it again to get real ANO */
10105 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10106 {
10107 if (dahdi_wink(p, idx)) goto quit;
10108 dtmfbuf[0] = 0;
10109 /* Wait for the first digit (up to 5 seconds). */
10110 res = ast_waitfordigit(chan, 5000);
10111 if (res <= 0) break;
10112 dtmfbuf[0] = res;
10113 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10114 }
10115 if (res > 0) {
10116 /* if E911, take off hook */
10117 if (p->sig == SIG_E911)
10118 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10119 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10120 }
10121 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10122 break;
10123 case SIG_FEATB:
10124 case SIG_SF_FEATB:
10125 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10126 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10127 break;
10128 case SIG_EMWINK:
10129 /* if we received a '*', we are actually receiving Feature Group D
10130 dial syntax, so use that mode; otherwise, fall through to normal
10131 mode
10132 */
10133 if (res == '*') {
10134 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10135 if (res > 0)
10136 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10137 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10138 break;
10139 }
10140 default:
10141 /* If we got the first digit, get the rest */
10142 len = 1;
10143 dtmfbuf[len] = '\0';
10144 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10145 if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10146 timeout = p->matchdigit_timeout;
10147 } else {
10148 timeout = p->interdigit_timeout;
10149 }
10150 res = ast_waitfordigit(chan, timeout);
10151 if (res < 0) {
10152 ast_debug(1, "waitfordigit returned < 0...\n");
10153 ast_hangup(chan);
10154 goto quit;
10155 } else if (res) {
10156 dtmfbuf[len++] = res;
10157 dtmfbuf[len] = '\0';
10158 } else {
10159 break;
10160 }
10161 }
10162 break;
10163 }
10164 }
10165 if (res == -1) {
10166 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10167 ast_hangup(chan);
10168 goto quit;
10169 } else if (res < 0) {
10170 ast_debug(1, "Got hung up before digits finished\n");
10171 ast_hangup(chan);
10172 goto quit;
10173 }
10174
10175 if (p->sig == SIG_FGC_CAMA) {
10176 char anibuf[100];
10177
10178 if (ast_safe_sleep(chan,1000) == -1) {
10179 ast_hangup(chan);
10180 goto quit;
10181 }
10182 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10184 res = my_getsigstr(chan, anibuf, "#", 10000);
10185 if ((res > 0) && (strlen(anibuf) > 2)) {
10186 if (anibuf[strlen(anibuf) - 1] == '#')
10187 anibuf[strlen(anibuf) - 1] = 0;
10188 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10189 }
10191 }
10192
10193 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10194 if (ast_strlen_zero(exten))
10195 ast_copy_string(exten, "s", sizeof(exten));
10196 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10197 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10198 if (exten[0] == '*') {
10199 char *stringp=NULL;
10200 ast_copy_string(exten2, exten, sizeof(exten2));
10201 /* Parse out extension and callerid */
10202 stringp=exten2 +1;
10203 s1 = strsep(&stringp, "*");
10204 s2 = strsep(&stringp, "*");
10205 if (s2) {
10206 if (!ast_strlen_zero(p->cid_num))
10207 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10208 else
10209 ast_set_callerid(chan, s1, NULL, s1);
10210 ast_copy_string(exten, s2, sizeof(exten));
10211 } else
10212 ast_copy_string(exten, s1, sizeof(exten));
10213 } else if (p->sig == SIG_FEATD)
10214 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10215 }
10216 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10217 if (exten[0] == '*') {
10218 char *stringp=NULL;
10219 ast_copy_string(exten2, exten, sizeof(exten2));
10220 /* Parse out extension and callerid */
10221 stringp=exten2 +1;
10222 s1 = strsep(&stringp, "#");
10223 s2 = strsep(&stringp, "#");
10224 if (s2) {
10225 if (!ast_strlen_zero(p->cid_num))
10226 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10227 else
10228 if (*(s1 + 2))
10229 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10230 ast_copy_string(exten, s2 + 1, sizeof(exten));
10231 } else
10232 ast_copy_string(exten, s1 + 2, sizeof(exten));
10233 } else
10234 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10235 }
10236 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10237 if (exten[0] == '*') {
10238 char *stringp=NULL;
10239 ast_copy_string(exten2, exten, sizeof(exten2));
10240 /* Parse out extension and callerid */
10241 stringp=exten2 +1;
10242 s1 = strsep(&stringp, "#");
10243 s2 = strsep(&stringp, "#");
10244 if (s2 && (*(s2 + 1) == '0')) {
10245 if (*(s2 + 2))
10246 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10247 }
10248 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10249 else ast_copy_string(exten, "911", sizeof(exten));
10250 } else
10251 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10252 }
10253 if (p->sig == SIG_FEATB) {
10254 if (exten[0] == '*') {
10255 char *stringp=NULL;
10256 ast_copy_string(exten2, exten, sizeof(exten2));
10257 /* Parse out extension and callerid */
10258 stringp=exten2 +1;
10259 s1 = strsep(&stringp, "#");
10260 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10261 } else
10262 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10263 }
10264 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10265 dahdi_wink(p, idx);
10266 /* some switches require a minimum guard time between
10267 the last FGD wink and something that answers
10268 immediately. This ensures it */
10269 if (ast_safe_sleep(chan, 100)) {
10270 ast_hangup(chan);
10271 goto quit;
10272 }
10273 }
10274 dahdi_ec_enable(p);
10275 if (NEED_MFDETECT(p)) {
10276 if (p->dsp) {
10277 if (!p->hardwaredtmf)
10279 else {
10280 ast_dsp_free(p->dsp);
10281 p->dsp = NULL;
10282 }
10283 }
10284 }
10285
10286 if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1,
10287 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
10288 ast_channel_exten_set(chan, exten);
10289 if (p->dsp) ast_dsp_digitreset(p->dsp);
10290 res = ast_pbx_run(chan);
10291 if (res) {
10292 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10293 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10294 }
10295 goto quit;
10296 } else {
10297 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, ast_channel_context(chan));
10298 sleep(2);
10299 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10300 if (res < 0)
10301 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10302 else
10303 sleep(1);
10304 res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
10305 if (res >= 0)
10306 ast_waitstream(chan, "");
10307 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10308 ast_hangup(chan);
10309 goto quit;
10310 }
10311 break;
10312 case SIG_FXOLS:
10313 case SIG_FXOGS:
10314 case SIG_FXOKS:
10315 /* Read the first digit */
10316 timeout = p->firstdigit_timeout;
10317 /* If starting a threeway call, never timeout on the first digit so someone
10318 can use flash-hook as a "hold" feature */
10319 if (p->subs[SUB_THREEWAY].owner)
10320 timeout = INT_MAX;
10321 while (len < AST_MAX_EXTENSION-1) {
10322 int is_exten_parking = 0;
10323
10324 /* Read digit unless it's supposed to be immediate, in which case the
10325 only answer is 's' */
10326 if (p->immediate)
10327 res = 's';
10328 else
10329 res = ast_waitfordigit(chan, timeout);
10330 timeout = 0;
10331 if (res < 0) {
10332 ast_debug(1, "waitfordigit returned < 0...\n");
10333 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10334 ast_hangup(chan);
10335 goto quit;
10336 } else if (res) {
10337 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10338 exten[len++]=res;
10339 exten[len] = '\0';
10340 }
10341 if (!ast_ignore_pattern(ast_channel_context(chan), exten)) {
10342 tone_zone_play_tone(p->subs[idx].dfd, -1);
10343 } else {
10344 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10345 }
10347 is_exten_parking = ast_parking_is_exten_park(ast_channel_context(chan), exten);
10348 }
10349 if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !is_exten_parking) {
10350 if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
10351 if (getforward) {
10352 /* Record this as the forwarding extension */
10353 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10354 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10355 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10356 if (res)
10357 break;
10358 usleep(500000);
10359 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10360 sleep(1);
10361 memset(exten, 0, sizeof(exten));
10362 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10363 len = 0;
10364 getforward = 0;
10365 } else {
10366 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10367 ast_channel_lock(chan);
10368 ast_channel_exten_set(chan, exten);
10369 if (!ast_strlen_zero(p->cid_num)) {
10370 if (!p->hidecallerid)
10371 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10372 else
10373 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10374 }
10375 if (!ast_strlen_zero(p->cid_name)) {
10376 if (!p->hidecallerid)
10377 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10378 }
10380 ast_channel_unlock(chan);
10381 dahdi_ec_enable(p);
10382 res = ast_pbx_run(chan);
10383 if (res) {
10384 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10385 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10386 }
10387 goto quit;
10388 }
10389 } else {
10390 /* It's a match, but they just typed a digit, and there is an ambiguous match,
10391 so just set the timeout to matchdigit_timeout and wait some more */
10392 timeout = p->matchdigit_timeout;
10393 }
10394 } else if (res == 0) {
10395 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10396 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10397 dahdi_wait_event(p->subs[idx].dfd);
10398 ast_hangup(chan);
10399 goto quit;
10400 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10401 ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
10402 /* Disable call waiting if enabled */
10403 p->callwaiting = 0;
10404 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10405 if (res) {
10406 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10407 ast_channel_name(chan), strerror(errno));
10408 }
10409 len = 0;
10410 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10411 memset(exten, 0, sizeof(exten));
10412 timeout = p->firstdigit_timeout;
10413
10414 } else if (!strcmp(exten, pickupexten)) {
10415 /* Scan all channels and see if there are any
10416 * ringing channels that have call groups
10417 * that equal this channels pickup group
10418 */
10419 if (idx == SUB_REAL) {
10420 /* Switch us from Third call to Call Wait */
10421 if (p->subs[SUB_THREEWAY].owner) {
10422 /* If you make a threeway call and the *8# a call, it should actually
10423 look like a callwait */
10427 }
10428 dahdi_ec_enable(p);
10429 if (ast_pickup_call(chan)) {
10430 ast_debug(1, "No call pickup possible...\n");
10431 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10432 dahdi_wait_event(p->subs[idx].dfd);
10433 }
10434 ast_hangup(chan);
10435 goto quit;
10436 } else {
10437 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10438 ast_hangup(chan);
10439 goto quit;
10440 }
10441
10442 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10443 ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
10444 /* Disable Caller*ID if enabled */
10445 p->hidecallerid = 1;
10450 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10451 if (res) {
10452 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10453 ast_channel_name(chan), strerror(errno));
10454 }
10455 len = 0;
10456 memset(exten, 0, sizeof(exten));
10457 timeout = p->firstdigit_timeout;
10458 } else if (p->callreturn && !strcmp(exten, "*69")) {
10459 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10460 break;
10461 } else if (!strcmp(exten, "*78")) {
10462 dahdi_dnd(p, 1);
10463 /* Do not disturb */
10464 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10465 getforward = 0;
10466 memset(exten, 0, sizeof(exten));
10467 len = 0;
10468 } else if (!strcmp(exten, "*79")) {
10469 dahdi_dnd(p, 0);
10470 /* Do not disturb */
10471 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10472 getforward = 0;
10473 memset(exten, 0, sizeof(exten));
10474 len = 0;
10475 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10476 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10477 getforward = 1;
10478 memset(exten, 0, sizeof(exten));
10479 len = 0;
10480 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10481 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10482 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10483 memset(p->call_forward, 0, sizeof(p->call_forward));
10484 getforward = 0;
10485 memset(exten, 0, sizeof(exten));
10486 len = 0;
10487 } else if ((p->transfer || p->canpark) && is_exten_parking
10488 && p->subs[SUB_THREEWAY].owner) {
10489 struct ast_bridge_channel *bridge_channel;
10490
10491 /*
10492 * This is a three way call, the main call being a real channel,
10493 * and we're parking the first call.
10494 */
10498 if (bridge_channel) {
10499 if (!ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten, NULL, NULL)) {
10500 /*
10501 * Swap things around between the three-way and real call so we
10502 * can hear where the channel got parked.
10503 */
10504 ast_mutex_lock(&p->lock);
10505 p->owner = p->subs[SUB_THREEWAY].owner;
10508
10509 ast_verb(3, "%s: Parked call\n", ast_channel_name(chan));
10511 ao2_ref(bridge_channel, -1);
10512 goto quit;
10513 }
10514 ao2_ref(bridge_channel, -1);
10515 }
10516 break;
10517 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10518 ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10519 /* Enable Caller*ID if enabled */
10520 p->hidecallerid = 0;
10522 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10523 if (res) {
10524 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10525 ast_channel_name(chan), strerror(errno));
10526 }
10527 len = 0;
10528 memset(exten, 0, sizeof(exten));
10529 timeout = p->firstdigit_timeout;
10530 } else if (!strcmp(exten, "*0")) {
10531 struct ast_channel *nbridge =
10533 struct dahdi_pvt *pbridge = NULL;
10534 RAII_VAR(struct ast_channel *, bridged, nbridge ? ast_channel_bridge_peer(nbridge) : NULL, ast_channel_cleanup);
10535
10536 /* set up the private struct of the bridged one, if any */
10537 if (nbridge && bridged) {
10538 pbridge = ast_channel_tech_pvt(bridged);
10539 }
10540 if (nbridge && pbridge &&
10541 (ast_channel_tech(nbridge) == &dahdi_tech) &&
10542 (ast_channel_tech(bridged) == &dahdi_tech) &&
10543 ISTRUNK(pbridge)) {
10544 int func = DAHDI_FLASH;
10545 /* Clear out the dial buffer */
10546 p->dop.dialstr[0] = '\0';
10547 /* flash hookswitch */
10548 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10549 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10550 ast_channel_name(nbridge), strerror(errno));
10551 }
10554 p->owner = p->subs[SUB_REAL].owner;
10556 ast_hangup(chan);
10557 goto quit;
10558 } else {
10559 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10560 dahdi_wait_event(p->subs[idx].dfd);
10561 tone_zone_play_tone(p->subs[idx].dfd, -1);
10564 p->owner = p->subs[SUB_REAL].owner;
10565 ast_hangup(chan);
10566 goto quit;
10567 }
10568 } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), exten, 1,
10569 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
10570 && !canmatch_featurecode(pickupexten, exten)) {
10571 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10572 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
10573 ast_channel_context(chan));
10574 break;
10575 }
10576 if (!timeout)
10577 timeout = p->interdigit_timeout;
10579 tone_zone_play_tone(p->subs[idx].dfd, -1);
10580 }
10581 break;
10582 case SIG_FXSLS:
10583 case SIG_FXSGS:
10584 case SIG_FXSKS:
10585 /* check for SMDI messages */
10586 if (p->use_smdi && p->smdi_iface) {
10588
10589 if (smdi_msg != NULL) {
10590 ast_channel_exten_set(chan, smdi_msg->fwd_st);
10591
10592 if (smdi_msg->type == 'B')
10593 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10594 else if (smdi_msg->type == 'N')
10595 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10596
10597 ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10598 } else {
10599 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10600 }
10601 }
10602
10603 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10604 number = smdi_msg->calling_st;
10605
10606 /* If we want caller id, we're in a prering state due to a polarity reversal
10607 * and we're set to use a polarity reversal to trigger the start of caller id,
10608 * grab the caller id and wait for ringing to start... */
10609 } else if (p->use_callerid && (ast_channel_state(chan) == AST_STATE_PRERING &&
10611 /* If set to use DTMF CID signalling, listen for DTMF */
10612 if (p->cid_signalling == CID_SIG_DTMF) {
10613 int k = 0;
10614 int off_ms;
10615 struct timeval start = ast_tvnow();
10616 int ms;
10617 cs = NULL;
10618 ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10619 dahdi_setlinear(p->subs[idx].dfd, 0);
10620 /*
10621 * We are the only party interested in the Rx stream since
10622 * we have not answered yet. We don't need or even want DTMF
10623 * emulation. The DTMF digits can come so fast that emulation
10624 * can drop some of them.
10625 */
10626 ast_channel_lock(chan);
10628 ast_channel_unlock(chan);
10629 off_ms = 4000;/* This is a typical OFF time between rings. */
10630 for (;;) {
10631 struct ast_frame *f;
10632
10633 ms = ast_remaining_ms(start, off_ms);
10634 res = ast_waitfor(chan, ms);
10635 if (res <= 0) {
10636 /*
10637 * We do not need to restore the dahdi_setlinear()
10638 * or AST_FLAG_END_DTMF_ONLY flag settings since we
10639 * are hanging up the channel.
10640 */
10641 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10642 "Exiting simple switch\n");
10643 ast_hangup(chan);
10644 goto quit;
10645 }
10646 f = ast_read(chan);
10647 if (!f)
10648 break;
10649 if (f->frametype == AST_FRAME_DTMF) {
10650 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10651 dtmfbuf[k++] = f->subclass.integer;
10652 }
10653 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10654 start = ast_tvnow();
10655 }
10656 ast_frfree(f);
10657 if (ast_channel_state(chan) == AST_STATE_RING ||
10659 break; /* Got ring */
10660 }
10661 ast_channel_lock(chan);
10663 ast_channel_unlock(chan);
10664 dtmfbuf[k] = '\0';
10665 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10666 /* Got cid and ring. */
10667 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10668 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10669 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10670 /* If first byte is NULL, we have no cid */
10671 if (!ast_strlen_zero(dtmfcid))
10672 number = dtmfcid;
10673 else
10674 number = NULL;
10675 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10676 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10678 if (cs) {
10679 int off_ms;
10680 struct timeval start;
10681 int ms;
10682 samples = 0;
10683#if 1
10684 bump_gains(p);
10685#endif
10686 /* Take out of linear mode for Caller*ID processing */
10687 dahdi_setlinear(p->subs[idx].dfd, 0);
10688
10689 /* First we wait and listen for the Caller*ID */
10690 for (;;) {
10691 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10692 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10693 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10694 callerid_free(cs);
10695 ast_hangup(chan);
10696 goto quit;
10697 }
10698 if (i & DAHDI_IOMUX_SIGEVENT) {
10699 res = dahdi_get_event(p->subs[idx].dfd);
10700 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10701 if (res == DAHDI_EVENT_NOALARM) {
10702 p->inalarm = 0;
10703 }
10704
10705 if (p->cid_signalling == CID_SIG_V23_JP) {
10706 if (res == DAHDI_EVENT_RINGBEGIN) {
10707 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10708 usleep(1);
10709 }
10710 } else {
10711 res = 0;
10712 break;
10713 }
10714 } else if (i & DAHDI_IOMUX_READ) {
10715 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10716 if (res < 0) {
10717 if (errno != ELAST) {
10718 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10719 callerid_free(cs);
10720 ast_hangup(chan);
10721 goto quit;
10722 }
10723 break;
10724 }
10725 samples += res;
10726
10727 if (p->cid_signalling == CID_SIG_V23_JP) {
10728 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10729 } else {
10730 res = callerid_feed(cs, buf, res, AST_LAW(p));
10731 }
10732 if (res < 0) {
10733 /*
10734 * The previous diagnostic message output likely
10735 * explains why it failed.
10736 */
10738 "Failed to decode CallerID on channel '%s'\n",
10739 ast_channel_name(chan));
10740 break;
10741 } else if (res)
10742 break;
10743 else if (samples > (8000 * 10))
10744 break;
10745 }
10746 }
10747 if (res == 1) {
10748 callerid_get(cs, &name, &number, &flags);
10749 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10750 }
10751
10752 if (p->cid_signalling == CID_SIG_V23_JP) {
10753 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10754 usleep(1);
10755 }
10756
10757 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10758 start = ast_tvnow();
10759 off_ms = 4000;/* This is a typical OFF time between rings. */
10760 for (;;) {
10761 struct ast_frame *f;
10762
10763 ms = ast_remaining_ms(start, off_ms);
10764 res = ast_waitfor(chan, ms);
10765 if (res <= 0) {
10766 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10767 "Exiting simple switch\n");
10768 ast_hangup(chan);
10769 goto quit;
10770 }
10771 if (!(f = ast_read(chan))) {
10772 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10773 ast_hangup(chan);
10774 goto quit;
10775 }
10776 ast_frfree(f);
10777 if (ast_channel_state(chan) == AST_STATE_RING ||
10779 break; /* Got ring */
10780 }
10781
10782 /* We must have a ring by now, so, if configured, lets try to listen for
10783 * distinctive ringing */
10785 len = 0;
10786 distMatches = 0;
10787 /* Clear the current ring data array so we don't have old data in it. */
10788 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10789 curRingData[receivedRingT] = 0;
10790 receivedRingT = 0;
10791 counter = 0;
10792 counter1 = 0;
10793 /* Check to see if context is what it should be, if not set to be. */
10794 if (strcmp(p->context,p->defcontext) != 0) {
10795 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10797 }
10798
10799 for (;;) {
10800 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10801 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10802 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10803 callerid_free(cs);
10804 ast_hangup(chan);
10805 goto quit;
10806 }
10807 if (i & DAHDI_IOMUX_SIGEVENT) {
10808 res = dahdi_get_event(p->subs[idx].dfd);
10809 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10810 if (res == DAHDI_EVENT_NOALARM) {
10811 p->inalarm = 0;
10812 }
10813 res = 0;
10814 /* Let us detect distinctive ring */
10815
10816 curRingData[receivedRingT] = p->ringt;
10817
10818 if (p->ringt < p->ringt_base/2)
10819 break;
10820 /* Increment the ringT counter so we can match it against
10821 values in chan_dahdi.conf for distinctive ring */
10822 if (++receivedRingT == ARRAY_LEN(curRingData))
10823 break;
10824 } else if (i & DAHDI_IOMUX_READ) {
10825 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10826 if (res < 0) {
10827 if (errno != ELAST) {
10828 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10829 callerid_free(cs);
10830 ast_hangup(chan);
10831 goto quit;
10832 }
10833 break;
10834 }
10835 if (p->ringt > 0) {
10836 if (!(--p->ringt)) {
10837 res = -1;
10838 break;
10839 }
10840 }
10841 }
10842 }
10843 /* this only shows up if you have n of the dring patterns filled in */
10844 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10845 for (counter = 0; counter < 3; counter++) {
10846 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10847 channel */
10848 distMatches = 0;
10849 for (counter1 = 0; counter1 < 3; counter1++) {
10850 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10851 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10852 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10853 curRingData[counter1]);
10854 distMatches++;
10855 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10856 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10857 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10858 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10859 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10860 distMatches++;
10861 }
10862 }
10863
10864 if (distMatches == 3) {
10865 /* The ring matches, set the context to whatever is for distinctive ring.. */
10866 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10868 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10869 break;
10870 }
10871 }
10872 }
10873 /* Restore linear mode (if appropriate) for Caller*ID processing */
10874 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10875#if 1
10876 restore_gains(p);
10877#endif
10878 } else
10879 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10880 } else {
10881 ast_log(LOG_WARNING, "Channel %s in prering "
10882 "state, but I have nothing to do. "
10883 "Terminating simple switch, should be "
10884 "restarted by the actual ring.\n",
10885 ast_channel_name(chan));
10886 ast_hangup(chan);
10887 goto quit;
10888 }
10889 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10890 if (p->cid_signalling == CID_SIG_DTMF) {
10891 int k = 0;
10892 int off_ms;
10893 struct timeval start;
10894 int ms;
10895 cs = NULL;
10896 dahdi_setlinear(p->subs[idx].dfd, 0);
10897 off_ms = 2000;
10898 start = ast_tvnow();
10899 for (;;) {
10900 struct ast_frame *f;
10901
10902 ms = ast_remaining_ms(start, off_ms);
10903 res = ast_waitfor(chan, ms);
10904 if (res <= 0) {
10905 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10906 "Exiting simple switch\n");
10907 ast_hangup(chan);
10908 goto quit;
10909 }
10910 f = ast_read(chan);
10911 if (!f) {
10912 /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10913 ast_hangup(chan);
10914 goto quit;
10915 }
10916 if (f->frametype == AST_FRAME_DTMF) {
10917 dtmfbuf[k++] = f->subclass.integer;
10918 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10919 start = ast_tvnow();
10920 }
10921 ast_frfree(f);
10922
10923 if (p->ringt_base == p->ringt)
10924 break;
10925 }
10926 dtmfbuf[k] = '\0';
10927 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10928 /* Got cid and ring. */
10929 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10930 ast_debug(1, "CID is '%s', flags %d\n",
10931 dtmfcid, flags);
10932 /* If first byte is NULL, we have no cid */
10933 if (!ast_strlen_zero(dtmfcid))
10934 number = dtmfcid;
10935 else
10936 number = NULL;
10937 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10938 } else {
10939 /* FSK Bell202 callerID */
10941 if (cs) {
10942#if 1
10943 bump_gains(p);
10944#endif
10945 samples = 0;
10946 len = 0;
10947 distMatches = 0;
10948 /* Clear the current ring data array so we don't have old data in it. */
10949 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10950 curRingData[receivedRingT] = 0;
10951 receivedRingT = 0;
10952 counter = 0;
10953 counter1 = 0;
10954 /* Check to see if context is what it should be, if not set to be. */
10955 if (strcmp(p->context,p->defcontext) != 0) {
10956 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10958 }
10959
10960 /* Take out of linear mode for Caller*ID processing */
10961 dahdi_setlinear(p->subs[idx].dfd, 0);
10962 for (;;) {
10963 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10964 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10965 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10966 callerid_free(cs);
10967 ast_hangup(chan);
10968 goto quit;
10969 }
10970 if (i & DAHDI_IOMUX_SIGEVENT) {
10971 res = dahdi_get_event(p->subs[idx].dfd);
10972 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10973 if (res == DAHDI_EVENT_NOALARM) {
10974 p->inalarm = 0;
10975 }
10976 /* If we get a PR event, they hung up while processing calerid */
10977 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10978 ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10980 callerid_free(cs);
10981 ast_hangup(chan);
10982 goto quit;
10983 }
10984 res = 0;
10985 /* Let us detect callerid when the telco uses distinctive ring */
10986
10987 curRingData[receivedRingT] = p->ringt;
10988
10989 if (p->ringt < p->ringt_base/2)
10990 break;
10991 /* Increment the ringT counter so we can match it against
10992 values in chan_dahdi.conf for distinctive ring */
10993 if (++receivedRingT == ARRAY_LEN(curRingData))
10994 break;
10995 } else if (i & DAHDI_IOMUX_READ) {
10996 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10997 if (res < 0) {
10998 if (errno != ELAST) {
10999 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11000 callerid_free(cs);
11001 ast_hangup(chan);
11002 goto quit;
11003 }
11004 break;
11005 }
11006 if (p->ringt > 0) {
11007 if (!(--p->ringt)) {
11008 res = -1;
11009 break;
11010 }
11011 }
11012 samples += res;
11013 res = callerid_feed(cs, buf, res, AST_LAW(p));
11014 if (res < 0) {
11015 /*
11016 * The previous diagnostic message output likely
11017 * explains why it failed.
11018 */
11020 "Failed to decode CallerID on channel '%s'\n",
11021 ast_channel_name(chan));
11022 break;
11023 } else if (res)
11024 break;
11025 else if (samples > (8000 * 10))
11026 break;
11027 }
11028 }
11029 if (res == 1) {
11030 callerid_get(cs, &name, &number, &flags);
11031 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
11032 }
11033 if (distinctiveringaftercid == 1) {
11034 /* Clear the current ring data array so we don't have old data in it. */
11035 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
11036 curRingData[receivedRingT] = 0;
11037 }
11038 receivedRingT = 0;
11039 ast_verb(3, "Detecting post-CID distinctive ring\n");
11040 for (;;) {
11041 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11042 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
11043 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11044 callerid_free(cs);
11045 ast_hangup(chan);
11046 goto quit;
11047 }
11048 if (i & DAHDI_IOMUX_SIGEVENT) {
11049 res = dahdi_get_event(p->subs[idx].dfd);
11050 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
11051 if (res == DAHDI_EVENT_NOALARM) {
11052 p->inalarm = 0;
11053 }
11054 res = 0;
11055 /* Let us detect callerid when the telco uses distinctive ring */
11056
11057 curRingData[receivedRingT] = p->ringt;
11058
11059 if (p->ringt < p->ringt_base/2)
11060 break;
11061 /* Increment the ringT counter so we can match it against
11062 values in chan_dahdi.conf for distinctive ring */
11063 if (++receivedRingT == ARRAY_LEN(curRingData))
11064 break;
11065 } else if (i & DAHDI_IOMUX_READ) {
11066 res = read(p->subs[idx].dfd, buf, sizeof(buf));
11067 if (res < 0) {
11068 if (errno != ELAST) {
11069 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11070 callerid_free(cs);
11071 ast_hangup(chan);
11072 goto quit;
11073 }
11074 break;
11075 }
11076 if (p->ringt > 0) {
11077 if (!(--p->ringt)) {
11078 res = -1;
11079 break;
11080 }
11081 }
11082 }
11083 }
11084 }
11086 /* this only shows up if you have n of the dring patterns filled in */
11087 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
11088
11089 for (counter = 0; counter < 3; counter++) {
11090 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
11091 channel */
11092 /* this only shows up if you have n of the dring patterns filled in */
11093 ast_verb(3, "Checking %d,%d,%d\n",
11094 p->drings.ringnum[counter].ring[0],
11095 p->drings.ringnum[counter].ring[1],
11096 p->drings.ringnum[counter].ring[2]);
11097 distMatches = 0;
11098 for (counter1 = 0; counter1 < 3; counter1++) {
11099 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11100 if (p->drings.ringnum[counter].ring[counter1] == -1) {
11101 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11102 curRingData[counter1]);
11103 distMatches++;
11104 }
11105 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11106 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11107 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11108 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11109 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11110 distMatches++;
11111 }
11112 }
11113 if (distMatches == 3) {
11114 /* The ring matches, set the context to whatever is for distinctive ring.. */
11115 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11117 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11118 break;
11119 }
11120 }
11121 }
11122 /* Restore linear mode (if appropriate) for Caller*ID processing */
11123 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11124#if 1
11125 restore_gains(p);
11126#endif
11127 if (res < 0) {
11128 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
11129 }
11130 } else
11131 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11132 }
11133 } else
11134 cs = NULL;
11135
11136 if (number)
11139
11140 ao2_cleanup(smdi_msg);
11141
11142 if (cs)
11143 callerid_free(cs);
11144
11145 my_handle_notify_message(chan, p, flags, -1);
11146
11147 ast_channel_lock(chan);
11149 ast_channel_rings_set(chan, 1);
11150 ast_channel_unlock(chan);
11151 p->ringt = p->ringt_base;
11152 res = ast_pbx_run(chan);
11153 if (res) {
11154 ast_hangup(chan);
11155 ast_log(LOG_WARNING, "PBX exited non-zero\n");
11156 }
11157 goto quit;
11158 default:
11159 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11160 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11161 if (res < 0)
11162 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11163 }
11164 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11165 if (res < 0)
11166 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11167 ast_hangup(chan);
11168quit:
11173 return NULL;
11174}
char * strsep(char **str, const char *delims)
#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:316
void callerid_free(struct callerid_state *cid)
This function frees callerid_state cid.
Definition: callerid.c:833
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:1101
#define CID_SIG_DTMF
Definition: callerid.h:62
struct callerid_state * callerid_new(int cid_signalling)
Create a callerID state machine.
Definition: callerid.c:130
#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:570
void callerid_get_dtmf(char *cidstring, char *number, int *flags)
Get and parse DTMF-based callerid.
Definition: callerid.c:211
#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:205
#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:833
static int restore_gains(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5239
static int unalloc_sub(struct dahdi_pvt *p, int x)
Definition: chan_dahdi.c:4534
static int dahdi_wink(struct dahdi_pvt *p, int index)
Definition: chan_dahdi.c:9889
static int dahdi_wait_event(int fd)
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition: chan_dahdi.c:852
static int canmatch_featurecode(const char *pickupexten, const char *exten)
Definition: chan_dahdi.c:9955
static int distinctiveringaftercid
Definition: chan_dahdi.c:799
static int bump_gains(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5225
#define AST_LAW(p)
Definition: chan_dahdi.c:712
static int dahdi_setlinear(int dfd, int linear)
Definition: chan_dahdi.c:4491
static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
Definition: chan_dahdi.c:3638
static int alloc_sub(struct dahdi_pvt *p, int x)
Definition: chan_dahdi.c:4497
#define NEED_MFDETECT(p)
Signaling types that need to use MF detection should be placed in this macro.
Definition: chan_dahdi.c:716
static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
Definition: chan_dahdi.c:9870
#define SMDI_MD_WAIT_TIMEOUT
Definition: chan_dahdi.c:673
static void swap_subs(struct dahdi_pvt *p, int a, int b)
Definition: chan_dahdi.c:4388
#define ISTRUNK(p)
Definition: chan_dahdi.c:781
#define POLARITY_IDLE
Definition: chan_dahdi.c:983
#define POLARITY_REV
Definition: chan_dahdi.c:984
static int ss_thread_count
Definition: chan_dahdi.c:835
#define SIG_FEATB
Definition: chan_dahdi.h:787
#define SIG_FGC_CAMA
Definition: chan_dahdi.h:790
#define SIG_SFWINK
Definition: chan_dahdi.h:799
#define SIG_EMWINK
Definition: chan_dahdi.h:784
#define SIG_SF_FEATB
Definition: chan_dahdi.h:802
#define SIG_FXOGS
Definition: chan_dahdi.h:796
#define SIG_SF_FEATDMF
Definition: chan_dahdi.h:801
#define SIG_FXOKS
Definition: chan_dahdi.h:797
#define SIG_FGC_CAMAMF
Definition: chan_dahdi.h:791
#define SIG_FEATDMF
Definition: chan_dahdi.h:786
#define SIG_EM_E1
Definition: chan_dahdi.h:803
#define SIG_SF_FEATD
Definition: chan_dahdi.h:800
#define SIG_FEATD
Definition: chan_dahdi.h:785
#define SIG_FEATDMF_TA
Definition: chan_dahdi.h:789
#define SIG_FXOLS
Definition: chan_dahdi.h:795
#define SIG_E911
Definition: chan_dahdi.h:788
#define SIG_EM
Definition: chan_dahdi.h:783
#define SIG_SF
Definition: chan_dahdi.h:798
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:3143
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:1558
void ast_party_number_init(struct ast_party_number *init)
Initialize the given number structure.
Definition: channel.c:1611
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2510
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:10569
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3130
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:4214
void ast_party_name_free(struct ast_party_name *doomed)
Destroy the party name contents.
Definition: channel.c:1605
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:7307
@ AST_FLAG_END_DTMF_ONLY
Definition: channel.h:1027
void ast_party_number_free(struct ast_party_number *doomed)
Destroy the party number contents.
Definition: channel.c:1658
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:10587
void ast_channel_context_set(struct ast_channel *chan, const char *value)
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:3019
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1541
#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:1301
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1848
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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:210
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:4770
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:4190
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:4205
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:6894
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:4210
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition: pickup.c:202
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:545
#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:491
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:702
char cid_num[AST_MAX_EXTENSION]
Caller ID number from an incoming call.
Definition: chan_dahdi.h:532
int ringt
Ring timeout timer??
Definition: chan_dahdi.h:609
int interdigit_timeout
Time (ms) to detect following digits (in an analog phone)
Definition: chan_dahdi.h:691
unsigned int usedistinctiveringdetection
TRUE if distinctive rings are to be detected.
Definition: chan_dahdi.h:407
int dtmfrelax
Definition: chan_dahdi.h:726
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:508
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:710
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:485
int ringt_base
Ring timeout base.
Definition: chan_dahdi.h:614
int cid_start
Definition: chan_dahdi.h:595
char defcontext[AST_MAX_CONTEXT]
Default distinctive ring context.
Definition: chan_dahdi.h:506
struct ast_dsp * dsp
Opaque DSP configuration structure.
Definition: chan_dahdi.h:700
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:686
int cid_signalling
Definition: chan_dahdi.h:594
unsigned int transfer
TRUE if call transfer is enabled.
Definition: chan_dahdi.h:386
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:541
int matchdigit_timeout
Time (ms) to wait, in case of ambiguous match (in an analog phone)
Definition: chan_dahdi.h:696
unsigned int use_callerid
TRUE if caller ID is used on this channel.
Definition: chan_dahdi.h:394
int polarity
Current line interface polarity. POLARITY_IDLE, POLARITY_REV.
Definition: chan_dahdi.h:742
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
Definition: chan_dahdi.h:488
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 1303 of file chan_dahdi.c.

1304{
1305 switch (tone) {
1307 return DAHDI_TONE_RINGTONE;
1309 return DAHDI_TONE_STUTTER;
1311 return DAHDI_TONE_CONGESTION;
1313 return DAHDI_TONE_DIALTONE;
1315 return DAHDI_TONE_DIALRECALL;
1316 case ANALOG_TONE_INFO:
1317 return DAHDI_TONE_INFO;
1318 default:
1319 return -1;
1320 }
1321}
@ 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 1323 of file chan_dahdi.c.

1324{
1325 int index;
1326
1327 switch (analogsub) {
1328 case ANALOG_SUB_REAL:
1329 index = SUB_REAL;
1330 break;
1332 index = SUB_CALLWAIT;
1333 break;
1335 index = SUB_THREEWAY;
1336 break;
1337 default:
1338 ast_log(LOG_ERROR, "Unidentified sub!\n");
1339 index = SUB_REAL;
1340 }
1341
1342 return index;
1343}
@ 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 20639 of file chan_dahdi.c.

◆ attempt_transfer()

static int attempt_transfer ( struct dahdi_pvt p)
static

Definition at line 7578 of file chan_dahdi.c.

7579{
7580 struct ast_channel *owner_real;
7581 struct ast_channel *owner_3way;
7582 enum ast_transfer_result xfer_res;
7583 int res = 0;
7584
7585 owner_real = ast_channel_ref(p->subs[SUB_REAL].owner);
7586 owner_3way = ast_channel_ref(p->subs[SUB_THREEWAY].owner);
7587
7588 ast_verb(3, "TRANSFERRING %s to %s\n",
7589 ast_channel_name(owner_3way), ast_channel_name(owner_real));
7590
7591 ast_channel_unlock(owner_real);
7592 ast_channel_unlock(owner_3way);
7594
7595 xfer_res = ast_bridge_transfer_attended(owner_3way, owner_real);
7596 if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
7598 res = -1;
7599 }
7600
7601 /* Must leave with these locked. */
7602 ast_channel_lock(owner_real);
7603 ast_mutex_lock(&p->lock);
7604
7605 ast_channel_unref(owner_real);
7606 ast_channel_unref(owner_3way);
7607
7608 return res;
7609}
ast_transfer_result
Definition: bridge.h:1102
@ AST_BRIDGE_TRANSFER_SUCCESS
Definition: bridge.h:1104
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
Definition: bridge.c:4746
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2997
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3008
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1141

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

13575{
13576 struct dahdi_pvt *p = *pvt;
13577
13578 if (p->inalarm)
13579 return 0;
13580
13581 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode))
13582 return analog_available(p->sig_pvt);
13583
13584 switch (p->sig) {
13585#if defined(HAVE_PRI)
13587 {
13588 struct sig_pri_chan *pvt_chan;
13589 int res;
13590
13591 pvt_chan = p->sig_pvt;
13592 res = sig_pri_available(&pvt_chan, is_specific_channel);
13593 *pvt = pvt_chan->chan_pvt;
13594 return res;
13595 }
13596#endif /* defined(HAVE_PRI) */
13597#if defined(HAVE_SS7)
13598 case SIG_SS7:
13599 return sig_ss7_available(p->sig_pvt);
13600#endif /* defined(HAVE_SS7) */
13601 default:
13602 break;
13603 }
13604
13605 if (p->locallyblocked || p->remotelyblocked) {
13606 return 0;
13607 }
13608
13609 /* If no owner definitely available */
13610 if (!p->owner) {
13611#ifdef HAVE_OPENR2
13612 /* Trust MFC/R2 */
13613 if (p->mfcr2) {
13614 if (p->mfcr2call) {
13615 return 0;
13616 } else {
13617 return 1;
13618 }
13619 }
13620#endif
13621 return 1;
13622 }
13623
13624 return 0;
13625}
#define SIG_PRI_LIB_HANDLE_CASES
Definition: chan_dahdi.h:817
#define SIG_SS7
Definition: chan_dahdi.h:811
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:457
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked. 1 maintenance, 2 blocked in hardware.
Definition: chan_dahdi.h:466
void * sig_pvt
Definition: chan_dahdi.h:770
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 16411 of file chan_dahdi.c.

16412{
16413 alarmstr[0] = '\0';
16414 if (spaninfo->alarms > 0) {
16415 if (spaninfo->alarms & DAHDI_ALARM_BLUE) {
16416 strcat(alarmstr, "BLU/");
16417 }
16418 if (spaninfo->alarms & DAHDI_ALARM_YELLOW) {
16419 strcat(alarmstr, "YEL/");
16420 }
16421 if (spaninfo->alarms & DAHDI_ALARM_RED) {
16422 strcat(alarmstr, "RED/");
16423 }
16424 if (spaninfo->alarms & DAHDI_ALARM_LOOPBACK) {
16425 strcat(alarmstr, "LB/");
16426 }
16427 if (spaninfo->alarms & DAHDI_ALARM_RECOVER) {
16428 strcat(alarmstr, "REC/");
16429 }
16430 if (spaninfo->alarms & DAHDI_ALARM_NOTOPEN) {
16431 strcat(alarmstr, "NOP/");
16432 }
16433 if (!strlen(alarmstr)) {
16434 strcat(alarmstr, "UUU/");
16435 }
16436 if (strlen(alarmstr)) {
16437 /* Strip trailing / */
16438 alarmstr[strlen(alarmstr) - 1] = '\0';
16439 }
16440 } else {
16441 if (spaninfo->numchans) {
16442 strcpy(alarmstr, "OK");
16443 } else {
16444 strcpy(alarmstr, "UNCONFIGURED");
16445 }
16446 }
16447}

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

18341{
18342 char *c, *chan;
18343 int x, start, finish;
18344 struct dahdi_pvt *tmp;
18345
18346 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
18347 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
18348 return -1;
18349 }
18350
18351 c = ast_strdupa(value);
18352
18353 while ((chan = strsep(&c, ","))) {
18354 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
18355 /* Range */
18356 } else if (sscanf(chan, "%30d", &start)) {
18357 /* Just one */
18358 finish = start;
18359 } else if (!strcasecmp(chan, "pseudo")) {
18360 finish = start = CHAN_PSEUDO;
18361 } else {
18362 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
18363 return -1;
18364 }
18365 if (finish < start) {
18366 ast_log(LOG_WARNING, "Silliness: %d < %d\n", start, finish);
18367 x = finish;
18368 finish = start;
18369 start = x;
18370 }
18371
18372 for (x = start; x <= finish; x++) {
18373 if (conf->wanted_channels_start &&
18374 (x < conf->wanted_channels_start ||
18375 x > conf->wanted_channels_end)
18376 ) {
18377 continue;
18378 }
18379 tmp = mkintf(x, conf, reload);
18380
18381 if (tmp) {
18382 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
18383 } else {
18384 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
18385 (reload == 1) ? "reconfigure" : "register", value);
18386 return -1;
18387 }
18388 if (x == CHAN_PSEUDO) {
18389 has_pseudo = 1;
18390 }
18391 }
18392 }
18393
18394 return 0;
18395}
static struct dahdi_pvt * mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
Definition: chan_dahdi.c:12591
static int has_pseudo
Definition: chan_dahdi.c:758
static int reload(void)
Definition: chan_dahdi.c:20615
#define CHAN_PSEUDO
Definition: chan_dahdi.c:747
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(), dahdi_pvt::sig, sig2str, strsep(), and value.

Referenced by process_dahdi().

◆ bump_gains()

static int bump_gains ( struct dahdi_pvt p)
static

Definition at line 5225 of file chan_dahdi.c.

5226{
5227 int res;
5228
5229 /* Bump receive gain by value stored in cid_rxgain */
5230 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5231 if (res) {
5232 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
5233 return -1;
5234 }
5235
5236 return 0;
5237}
static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
Definition: chan_dahdi.c:5220
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:562
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 11182 of file chan_dahdi.c.

11183{
11184 int x;
11185 int sum = 0;
11186
11187 if (!len)
11188 return 0;
11189
11190 for (x = 0; x < len; x++)
11191 sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11192
11193 return sum / len;
11194}
#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 9955 of file chan_dahdi.c.

9956{
9957 int extlen = strlen(exten);
9958
9959 if (!extlen) {
9960 return 1;
9961 }
9962
9963 if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
9964 return 1;
9965 }
9966 /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
9967 if (exten[0] == '*' && extlen < 3) {
9968 if (extlen == 1) {
9969 return 1;
9970 }
9971 /* "*0" should be processed before it gets here */
9972 switch (exten[1]) {
9973 case '6':
9974 case '7':
9975 case '8':
9976 return 1;
9977 }
9978 }
9979 return 0;
9980}

Referenced by analog_ss_thread().

◆ check_for_conference()

static int check_for_conference ( struct dahdi_pvt p)
static

Definition at line 7611 of file chan_dahdi.c.

7612{
7613 struct dahdi_confinfo ci;
7614 /* Fine if we already have a master, etc */
7615 if (p->master || (p->confno > -1))
7616 return 0;
7617 memset(&ci, 0, sizeof(ci));
7618 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
7619 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
7620 return 0;
7621 }
7622 /* If we have no master and don't have a confno, then
7623 if we're in a conference, it's probably a MeetMe room or
7624 some such, so don't let us 3-way out! */
7625 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
7626 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
7627 return 1;
7628 }
7629 return 0;
7630}
struct dahdi_pvt * master
Definition: chan_dahdi.h:135
int confno
Definition: chan_dahdi.h:563
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 4787 of file chan_dahdi.c.

4788{
4789 /* If the conference already exists, and we're already in it
4790 don't bother doing anything */
4791 struct dahdi_confinfo zi;
4792
4793 memset(&zi, 0, sizeof(zi));
4794 zi.chan = 0;
4795
4796 if (slavechannel > 0) {
4797 /* If we have only one slave, do a digital mon */
4798 zi.confmode = DAHDI_CONF_DIGITALMON;
4799 zi.confno = slavechannel;
4800 } else {
4801 if (!idx) {
4802 /* Real-side and pseudo-side both participate in conference */
4803 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
4804 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
4805 } else
4806 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
4807 zi.confno = p->confno;
4808 }
4809 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
4810 return 0;
4811 if (c->dfd < 0)
4812 return 0;
4813 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4814 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
4815 return -1;
4816 }
4817 if (slavechannel < 1) {
4818 p->confno = zi.confno;
4819 }
4820 c->curconf = zi;
4821 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4822 return 0;
4823}

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

4837{
4838 struct dahdi_confinfo zi;
4839 if (/* Can't delete if there's no dfd */
4840 (c->dfd < 0) ||
4841 /* Don't delete from the conference if it's not our conference */
4842 !isourconf(p, c)
4843 /* Don't delete if we don't think it's conferenced at all (implied) */
4844 ) return 0;
4845 memset(&zi, 0, sizeof(zi));
4846 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4847 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
4848 return -1;
4849 }
4850 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4851 memcpy(&c->curconf, &zi, sizeof(c->curconf));
4852 return 0;
4853}
static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
Definition: chan_dahdi.c:4825

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

9571{
9572 struct ast_str *chan_name;
9573 int x, y;
9574
9575 /* Create the new channel name tail. */
9576 if (!(chan_name = ast_str_create(32))) {
9577 return NULL;
9578 }
9579 if (i->channel == CHAN_PSEUDO) {
9580 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
9581#if defined(HAVE_PRI)
9582 } else if (i->pri) {
9583 ast_mutex_lock(&i->pri->lock);
9584 y = ++i->pri->new_chan_seq;
9585 if (is_outgoing) {
9586 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
9587 address[0] = '\0';
9588 } else if (ast_strlen_zero(i->cid_subaddr)) {
9589 /* Put in caller-id number only since there is no subaddress. */
9590 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
9591 } else {
9592 /* Put in caller-id number and subaddress. */
9593 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
9594 i->cid_subaddr, (unsigned)y);
9595 }
9596 ast_mutex_unlock(&i->pri->lock);
9597#endif /* defined(HAVE_PRI) */
9598 } else {
9599 y = 1;
9600 do {
9601 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
9602 for (x = 0; x < 3; ++x) {
9603 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
9604 ast_channel_name(i->subs[x].owner) + 6)) {
9605 break;
9606 }
9607 }
9608 ++y;
9609 } while (x < 3);
9610 }
9611 return chan_name;
9612}
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:543
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 2038 of file chan_dahdi.c.

2039{
2040 char ch_name[23];
2041
2042 if (p->channel < CHAN_PSEUDO) {
2043 /* No B channel */
2044 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
2045 } else if (p->channel == CHAN_PSEUDO) {
2046 /* Pseudo channel */
2047 strcpy(ch_name, "pseudo");
2048 } else {
2049 /* Real channel */
2050 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
2051 }
2052 publish_dahdichannel(chan, p->group, p->span, ch_name);
2053}
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:2011
ast_group_t group
Bitmapped groups this belongs to.
Definition: chan_dahdi.h:558

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

6770{
6771 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6772 int res = 0;
6773 int idx;
6774 ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
6775 ast_mutex_lock(&p->lock);
6776 idx = dahdi_get_index(ast, p, 0);
6777 if (idx < 0)
6778 idx = SUB_REAL;
6779 /* nothing to do if a radio channel */
6780 if ((p->radio || (p->oprmode < 0))) {
6782 return 0;
6783 }
6784
6785 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
6786 res = analog_answer(p->sig_pvt, ast);
6788 return res;
6789 }
6790
6791 switch (p->sig) {
6792#if defined(HAVE_PRI)
6794 res = sig_pri_answer(p->sig_pvt, ast);
6795 break;
6796#endif /* defined(HAVE_PRI) */
6797#if defined(HAVE_SS7)
6798 case SIG_SS7:
6799 res = sig_ss7_answer(p->sig_pvt, ast);
6800 break;
6801#endif /* defined(HAVE_SS7) */
6802#ifdef HAVE_OPENR2
6803 case SIG_MFCR2:
6804 if (!p->mfcr2_call_accepted) {
6805 /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
6806 openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
6807 p->mfcr2_answer_pending = 1;
6808 if (p->mfcr2_charge_calls) {
6809 ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
6810 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
6811 } else {
6812 ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
6813 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
6814 }
6815 } else {
6816 ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
6817 dahdi_r2_answer(p);
6818 }
6819 break;
6820#endif
6821 case 0:
6823 return 0;
6824 default:
6825 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
6826 res = -1;
6827 break;
6828 }
6830 return res;
6831}
#define SIG_MFCR2
Definition: chan_dahdi.h:814
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 5463 of file chan_dahdi.c.

5464{
5465 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5466 int x, res, mysig;
5467 char *dest;
5469 AST_APP_ARG(group); /* channel/group token */
5470 AST_APP_ARG(ext); /* extension token */
5471 //AST_APP_ARG(opts); /* options token */
5472 AST_APP_ARG(other); /* Any remaining unused arguments */
5473 );
5474
5475 ast_mutex_lock(&p->lock);
5476 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
5477
5478 /* Split the dialstring */
5479 dest = ast_strdupa(rdest);
5480 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
5481 if (!args.ext) {
5482 args.ext = "";
5483 }
5484
5485#if defined(HAVE_PRI)
5487 char *subaddr;
5488
5489 sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
5490
5491 /* Remove any subaddress for uniformity with incoming calls. */
5492 subaddr = strchr(p->exten, ':');
5493 if (subaddr) {
5494 *subaddr = '\0';
5495 }
5496 } else
5497#endif /* defined(HAVE_PRI) */
5498 {
5499 ast_copy_string(p->exten, args.ext, sizeof(p->exten));
5500 }
5501
5502 if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
5503 p->subs[SUB_REAL].needbusy = 1;
5505 return 0;
5506 }
5508 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
5510 return -1;
5511 }
5512 p->waitingfordt.tv_sec = 0;
5513 p->dialednone = 0;
5514 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
5515 {
5516 /* Special pseudo -- automatically up */
5519 return 0;
5520 }
5521 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
5522 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
5523 if (res)
5524 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
5525 p->outgoing = 1;
5526
5528 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
5529 } else {
5530 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5531 }
5532
5533#ifdef HAVE_PRI
5535 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
5536 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
5538 return res;
5539 }
5540#endif
5541
5542#if defined(HAVE_SS7)
5543 if (p->sig == SIG_SS7) {
5544 res = sig_ss7_call(p->sig_pvt, ast, rdest);
5546 return res;
5547 }
5548#endif /* defined(HAVE_SS7) */
5549
5550 /* If this is analog signalling we can exit here */
5551 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
5552 p->callwaitrings = 0;
5553 res = analog_call(p->sig_pvt, ast, rdest, timeout);
5555 return res;
5556 }
5557
5558 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
5559 switch (mysig) {
5560 case 0:
5561 /* Special pseudo -- automatically up*/
5563 break;
5564 case SIG_MFCR2:
5565 break;
5566 default:
5567 ast_debug(1, "not yet implemented\n");
5569 return -1;
5570 }
5571
5572#ifdef HAVE_OPENR2
5573 if (p->mfcr2) {
5574 openr2_calling_party_category_t chancat;
5575 int callres = 0;
5576 char *c, *l;
5577
5578 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
5579 p->dialdest[0] = '\0';
5580
5581 c = args.ext;
5582 if (!p->hidecallerid) {
5584 } else {
5585 l = NULL;
5586 }
5587 if (strlen(c) < p->stripmsd) {
5588 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
5590 return -1;
5591 }
5592 p->dialing = 1;
5593 chancat = dahdi_r2_get_channel_category(ast);
5594 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
5595 if (-1 == callres) {
5597 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
5598 return -1;
5599 }
5600 p->mfcr2_call_accepted = 0;
5601 p->mfcr2_progress_sent = 0;
5603 }
5604#endif /* HAVE_OPENR2 */
5606 return 0;
5607}
static int dahdi_sig_pri_lib_handles(int signaling)
Definition: chan_dahdi.h:831
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:460
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:344
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:299
char * str
Subscriber phone number (Malloced)
Definition: channel.h:293
char dialdest[256]
Delayed dialing for E911. Overlap digits for ISDN.
Definition: chan_dahdi.h:719
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:630
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:697
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
Definition: chan_dahdi.h:621
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 5429 of file chan_dahdi.c.

5430{
5431 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5432
5434 if (p->cidspill) {
5435 ast_log(LOG_WARNING, "Spill already exists?!?\n");
5436 ast_free(p->cidspill);
5437 }
5438
5439 /*
5440 * SAS: Subscriber Alert Signal, 440Hz for 300ms
5441 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
5442 */
5443 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
5444 return -1;
5445 save_conference(p);
5446 /* Silence */
5447 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
5448 if (!p->callwaitrings && p->callwaitingcallerid) {
5449 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
5450 p->callwaitcas = 1;
5451 p->cidlen = 2400 + 680 + READ_SIZE * 4;
5452 } else {
5453 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
5454 p->callwaitcas = 0;
5455 p->cidlen = 2400 + READ_SIZE * 4;
5456 }
5457 p->cidpos = 0;
5458 send_callerid(p);
5459
5460 return 0;
5461}
#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:271
#define CALLWAITING_REPEAT_SAMPLES
Definition: chan_dahdi.c:870
static int save_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5306
#define READ_SIZE
Definition: chan_dahdi.c:864
static int send_callerid(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5393
unsigned char * cidspill
Analog caller ID waveform sample buffer.
Definition: chan_dahdi.h:603
int cidlen
Length of the cidspill buffer containing samples.
Definition: chan_dahdi.h:607
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:628
int cidpos
Position in the cidspill buffer to send out next.
Definition: chan_dahdi.h:605

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

14249{
14250 struct dahdi_pvt *p;
14251 struct dahdi_pvt *exitpvt;
14252 struct dahdi_starting_point start;
14253 int groupmatched = 0;
14254 int channelmatched = 0;
14255
14257 p = determine_starting_point(dest, &start);
14258 if (!p) {
14260 return -1;
14261 }
14262 exitpvt = p;
14263 for (;;) {
14264 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
14265 /* We found a potential match. call the callback */
14266 struct ast_str *device_name;
14267 char *dash;
14268 const char *monitor_type;
14269 char dialstring[AST_CHANNEL_NAME];
14270 char full_device_name[AST_CHANNEL_NAME];
14271
14274 break;
14278#if defined(HAVE_PRI)
14280 /*
14281 * ISDN is in a trunk busy condition so we need to monitor
14282 * the span congestion device state.
14283 */
14284 snprintf(full_device_name, sizeof(full_device_name),
14285 "DAHDI/I%d/congestion", p->pri->span);
14286 } else
14287#endif /* defined(HAVE_PRI) */
14288 {
14289#if defined(HAVE_PRI)
14290 device_name = create_channel_name(p, 1, "");
14291#else
14292 device_name = create_channel_name(p);
14293#endif /* defined(HAVE_PRI) */
14294 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14295 device_name ? ast_str_buffer(device_name) : "");
14296 ast_free(device_name);
14297 /*
14298 * The portion after the '-' in the channel name is either a random
14299 * number, a sequence number, or a subchannel number. None are
14300 * necessary so strip them off.
14301 */
14302 dash = strrchr(full_device_name, '-');
14303 if (dash) {
14304 *dash = '\0';
14305 }
14306 }
14307 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14308
14309 /*
14310 * Analog can only do generic monitoring.
14311 * ISDN is in a trunk busy condition and any "device" is going
14312 * to be busy until a B channel becomes available. The generic
14313 * monitor can do this task.
14314 */
14315 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14316 callback(inbound,
14317#if defined(HAVE_PRI)
14318 p->pri ? p->pri->cc_params : p->cc_params,
14319#else
14320 p->cc_params,
14321#endif /* defined(HAVE_PRI) */
14322 monitor_type, full_device_name, dialstring, NULL);
14323 break;
14324 }
14325 }
14326 p = start.backwards ? p->prev : p->next;
14327 if (!p) {
14328 p = start.backwards ? ifend : iflist;
14329 }
14330 if (p == exitpvt) {
14331 break;
14332 }
14333 }
14335 return 0;
14336}
#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:882
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:13541
static struct ast_str * create_channel_name(struct dahdi_pvt *i)
Definition: chan_dahdi.c:9569
static struct dahdi_pvt * ifend
Definition: chan_dahdi.c:993
static struct dahdi_pvt * determine_starting_point(const char *data, struct dahdi_starting_point *param)
Definition: chan_dahdi.c:13844
#define AST_CHANNEL_NAME
Definition: channel.h:173
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
struct dahdi_pvt * prev
Definition: chan_dahdi.h:170
struct ast_cc_config_params * cc_params
Definition: chan_dahdi.h:771

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, callback(), 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 1060 of file chan_dahdi.c.

1061{
1062 /* recall that if a field is not included here it is initialized
1063 * to 0 or equivalent
1064 */
1065 struct dahdi_chan_conf conf = {
1066#ifdef HAVE_PRI
1067 .pri.pri = {
1068 .nsf = PRI_NSF_NONE,
1069 .switchtype = PRI_SWITCH_NI2,
1070 .dialplan = PRI_UNKNOWN + 1,
1071 .localdialplan = PRI_NATIONAL_ISDN + 1,
1072 .nodetype = PRI_CPE,
1073 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
1074
1075#if defined(HAVE_PRI_CCSS)
1076 .cc_ptmp_recall_mode = 1,/* specificRecall */
1077 .cc_qsig_signaling_link_req = 1,/* retain */
1078 .cc_qsig_signaling_link_rsp = 1,/* retain */
1079#endif /* defined(HAVE_PRI_CCSS) */
1080
1081 .minunused = 2,
1082 .idleext = "",
1083 .idledial = "",
1084 .internationalprefix = "",
1085 .nationalprefix = "",
1086 .localprefix = "",
1087 .privateprefix = "",
1088 .unknownprefix = "",
1089 .colp_send = SIG_PRI_COLP_UPDATE,
1090 .resetinterval = -1,
1091 },
1092#endif
1093#if defined(HAVE_SS7)
1094 .ss7.ss7 = {
1095 .called_nai = SS7_NAI_NATIONAL,
1096 .calling_nai = SS7_NAI_NATIONAL,
1097 .internationalprefix = "",
1098 .nationalprefix = "",
1099 .subscriberprefix = "",
1100 .unknownprefix = "",
1101 .networkroutedprefix = ""
1102 },
1103#endif /* defined(HAVE_SS7) */
1104#ifdef HAVE_OPENR2
1105 .mfcr2 = {
1106 .variant = OR2_VAR_ITU,
1107 .mfback_timeout = -1,
1108 .metering_pulse_timeout = -1,
1109 .max_ani = 10,
1110 .max_dnis = 4,
1111 .get_ani_first = -1,
1112#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
1113 .skip_category_request = -1,
1114#endif
1115 .call_files = 0,
1116 .allow_collect_calls = 0,
1117 .charge_calls = 1,
1118 .accept_on_offer = 1,
1119 .forced_release = 0,
1120 .double_answer = 0,
1121 .immediate_accept = -1,
1122#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
1123 .dtmf_dialing = -1,
1124 .dtmf_detection = -1,
1125 .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
1126 .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
1127#endif
1128#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
1129 .dtmf_end_timeout = -1,
1130#endif
1131 .logdir = "",
1132 .r2proto_file = "",
1133 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
1134 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
1135 },
1136#endif
1137 .chan = {
1138 .context = "default",
1139 .immediatering = 1,
1140 .cid_num = "",
1141 .cid_name = "",
1142 .cid_tag = "",
1143 .mohinterpret = "default",
1144 .mohsuggest = "",
1145 .parkinglot = "",
1146 .transfertobusy = 1,
1147 .dialmode = 0,
1148
1149 .ani_info_digits = 2,
1150 .ani_wink_time = 1000,
1151 .ani_timeout = 10000,
1152
1153 .cid_signalling = CID_SIG_BELL,
1154 .cid_start = CID_START_RING,
1155 .dahditrcallerid = 0,
1156 .use_callerid = 1,
1157 .sig = -1,
1158 .outsigmod = -1,
1159
1160 .cid_rxgain = +5.0,
1161
1162 .tonezone = -1,
1163
1164 .echocancel.head.tap_length = 1,
1165
1166 .busycount = 3,
1167
1168 .accountcode = "",
1169
1170 .mailbox = "",
1171
1172#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
1173 .mwisend_fsk = 1,
1174#endif
1175 .polarityonanswerdelay = 600,
1176
1177 .sendcalleridafter = DEFAULT_CIDRINGS,
1178
1179 .buf_policy = DAHDI_POLICY_IMMEDIATE,
1180 .buf_no = numbufs,
1181 .usefaxbuffers = 0,
1182 .cc_params = ast_cc_config_params_init(),
1183 .firstdigit_timeout = ANALOG_FIRST_DIGIT_TIMEOUT,
1184 .interdigit_timeout = ANALOG_INTER_DIGIT_TIMEOUT,
1185 .matchdigit_timeout = ANALOG_MATCH_DIGIT_TIMEOUT,
1186 },
1187 .timing = {
1188 .prewinktime = -1,
1189 .preflashtime = -1,
1190 .winktime = -1,
1191 .flashtime = -1,
1192 .starttime = -1,
1193 .rxwinktime = -1,
1194 .rxflashtime = -1,
1195 .debouncetime = -1
1196 },
1197 .is_sig_auto = 1,
1198 .ignore_failed_channels = 1,
1199 .smdi_port = "/dev/ttyS0",
1200 };
1201
1202 return conf;
1203}
#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:801
#define DEFAULT_CIDRINGS
Typically, how many rings before we should send Caller*ID.
Definition: chan_dahdi.c:710
#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:1022

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

4464{
4465 if (fd > 0)
4466 close(fd);
4467}

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

4470{
4471 dahdi_close(chan_pvt->subs[sub_num].dfd);
4472 chan_pvt->subs[sub_num].dfd = -1;
4473}
static void dahdi_close(int fd)
Definition: chan_dahdi.c:4463

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

4914{
4915 int needconf = 0;
4916 int x;
4917 int useslavenative;
4918 struct dahdi_pvt *slave = NULL;
4919
4920 useslavenative = isslavenative(p, &slave);
4921 /* Start with the obvious, general stuff */
4922 for (x = 0; x < 3; x++) {
4923 /* Look for three way calls */
4924 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
4925 conf_add(p, &p->subs[x], x, 0);
4926 needconf++;
4927 } else {
4928 conf_del(p, &p->subs[x], x);
4929 }
4930 }
4931 /* If we have a slave, add him to our conference now. or DAX
4932 if this is slave native */
4933 for (x = 0; x < MAX_SLAVES; x++) {
4934 if (p->slaves[x]) {
4935 if (useslavenative)
4936 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
4937 else {
4938 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
4939 needconf++;
4940 }
4941 }
4942 }
4943 /* If we're supposed to be in there, do so now */
4944 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
4945 if (useslavenative)
4946 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
4947 else {
4948 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
4949 needconf++;
4950 }
4951 }
4952 /* If we have a master, add ourselves to his conference */
4953 if (p->master) {
4954 if (isslavenative(p->master, NULL)) {
4956 } else {
4957 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
4958 }
4959 }
4960 if (!needconf) {
4961 /* Nobody is left (or should be left) in our conference.
4962 Kill it. */
4963 p->confno = -1;
4964 }
4965 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
4966}
static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
Definition: chan_dahdi.c:4836
static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
Definition: chan_dahdi.c:4787
static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
Definition: chan_dahdi.c:4855
#define GET_CHANNEL(p)
Definition: chan_dahdi.c:1250
#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 5269 of file chan_dahdi.c.

5270{
5271 int x, res;
5272
5273 x = muted;
5274#if defined(HAVE_PRI) || defined(HAVE_SS7)
5275 switch (p->sig) {
5276#if defined(HAVE_PRI)
5278 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
5279 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
5280 break;
5281 }
5282 /* Fall through */
5283#endif /* defined(HAVE_PRI) */
5284#if defined(HAVE_SS7)
5285 case SIG_SS7:
5286#endif /* defined(HAVE_SS7) */
5287 {
5288 int y = 1;
5289
5290 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
5291 if (res)
5292 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
5293 p->channel, strerror(errno));
5294 }
5295 break;
5296 default:
5297 break;
5298 }
5299#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
5300 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
5301 if (res < 0)
5302 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
5303 return res;
5304}

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

11621{
11622 struct dahdi_pvt *cur;
11623 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
11624 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
11626 int ret = RESULT_FAILURE; /* be pessimistic */
11627
11628 ast_debug(1, "channel range caps: %d - %d\n", start, end);
11630 for (cur = iflist; cur; cur = cur->next) {
11631 if (cur->channel >= start && cur->channel <= end) {
11633 "channel range %d-%d is occupied\n",
11634 start, end);
11635 goto out;
11636 }
11637 }
11638#ifdef HAVE_PRI
11639 {
11640 int i, x;
11641 for (x = 0; x < NUM_SPANS; x++) {
11642 struct dahdi_pri *pri = pris + x;
11643
11644 if (!pris[x].pri.pvts[0]) {
11645 break;
11646 }
11647 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
11648 int channo = pri->dchannels[i];
11649
11650 if (!channo) {
11651 break;
11652 }
11653 if (!pri->pri.fds[i]) {
11654 break;
11655 }
11656 if (channo >= start && channo <= end) {
11658 "channel range %d-%d is occupied by span %d\n",
11659 start, end, x + 1);
11660 goto out;
11661 }
11662 }
11663 }
11664 }
11665#endif
11666 if (!default_conf.chan.cc_params || !base_conf.chan.cc_params ||
11667 !conf.chan.cc_params) {
11668 goto out;
11669 }
11670 default_conf.wanted_channels_start = start;
11671 base_conf.wanted_channels_start = start;
11672 conf.wanted_channels_start = start;
11673 default_conf.wanted_channels_end = end;
11674 base_conf.wanted_channels_end = end;
11675 conf.wanted_channels_end = end;
11676 if (setup_dahdi_int(0, &default_conf, &base_conf, &conf) == 0) {
11677 ret = RESULT_SUCCESS;
11678 }
11679out:
11682 ast_cc_config_params_destroy(conf.chan.cc_params);
11684 return ret;
11685}
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition: ccss.c:698
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:20062
static struct dahdi_chan_conf dahdi_chan_conf_default(void)
Definition: chan_dahdi.c:1060
#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:1056
struct dahdi_pvt chan
Definition: chan_dahdi.c:1023
int wanted_channels_start
Don't create channels below this number.
Definition: chan_dahdi.c:1050
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 15866 of file chan_dahdi.c.

15867{
15868 int start;
15869 int end;
15870 int ret;
15871
15872 switch (cmd) {
15873 case CLI_INIT:
15874 e->command = "dahdi create channels";
15875 e->usage = "Usage: dahdi create channels <from> [<to>] - a range of channels\n"
15876 " dahdi create channels new - add channels not yet created\n"
15877 "For ISDN and SS7 the range should include complete spans.\n";
15878 return NULL;
15879 case CLI_GENERATE:
15880 return NULL;
15881 }
15882 if ((a->argc < 4) || a->argc > 5) {
15883 return CLI_SHOWUSAGE;
15884 }
15885 if (a->argc == 4 && !strcmp(a->argv[3], "new")) {
15886 ret = dahdi_create_channel_range(0, 0);
15887 return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15888 }
15889 start = atoi(a->argv[3]);
15890 if (start <= 0) {
15891 ast_cli(a->fd, "Invalid starting channel number '%s'.\n",
15892 a->argv[3]);
15893 return CLI_FAILURE;
15894 }
15895 if (a->argc == 5) {
15896 end = atoi(a->argv[4]);
15897 if (end <= 0) {
15898 ast_cli(a->fd, "Invalid ending channel number '%s'.\n",
15899 a->argv[4]);
15900 return CLI_FAILURE;
15901 }
15902 } else {
15903 end = start;
15904 }
15905 if (end < start) {
15906 ast_cli(a->fd,
15907 "range end (%d) is smaller than range start (%d)\n",
15908 end, start);
15909 return CLI_FAILURE;
15910 }
15911 ret = dahdi_create_channel_range(start, end);
15912 return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15913}
static int dahdi_create_channel_range(int start, int end)
Definition: chan_dahdi.c:11620
#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 11538 of file chan_dahdi.c.

11539{
11540 struct dahdi_pvt *cur;
11541 struct dahdi_pvt *next;
11542 int destroyed_first = 0;
11543 int destroyed_last = 0;
11544
11546 ast_debug(1, "range: %d-%d\n", start, end);
11547 for (cur = iflist; cur; cur = next) {
11548 next = cur->next;
11549 if (cur->channel >= start && cur->channel <= end) {
11550 int x = DAHDI_FLASH;
11551
11552 if (cur->channel > destroyed_last) {
11553 destroyed_last = cur->channel;
11554 }
11555 if (destroyed_first < 1 || cur->channel < destroyed_first) {
11556 destroyed_first = cur->channel;
11557 }
11558 ast_debug(3, "Destroying %d\n", cur->channel);
11559 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11560 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11561
11562 destroy_channel(cur, 1);
11564 }
11565 }
11567 if (destroyed_first > start || destroyed_last < end) {
11568 ast_debug(1, "Asked to destroy %d-%d, destroyed %d-%d,\n",
11569 start, end, destroyed_first, destroyed_last);
11570 }
11571}
static void destroy_channel(struct dahdi_pvt *cur, int now)
Definition: chan_dahdi.c:5977
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
struct ast_module * self
Definition: module.h:356

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

15823{
15824 int start;
15825 int end;
15826 switch (cmd) {
15827 case CLI_INIT:
15828 e->command = "dahdi destroy channels";
15829 e->usage =
15830 "Usage: dahdi destroy channels <from_channel> [<to_channel>]\n"
15831 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15832 return NULL;
15833 case CLI_GENERATE:
15834 return NULL;
15835 }
15836 if ((a->argc < 4) || a->argc > 5) {
15837 return CLI_SHOWUSAGE;
15838 }
15839 start = atoi(a->argv[3]);
15840 if (start < 1) {
15841 ast_cli(a->fd, "Invalid starting channel number %s.\n",
15842 a->argv[4]);
15843 return CLI_FAILURE;
15844 }
15845 if (a->argc == 5) {
15846 end = atoi(a->argv[4]);
15847 if (end < 1) {
15848 ast_cli(a->fd, "Invalid ending channel number %s.\n",
15849 a->argv[4]);
15850 return CLI_FAILURE;
15851 }
15852 } else {
15853 end = start;
15854 }
15855
15856 if (end < start) {
15857 ast_cli(a->fd,
15858 "range end (%d) is smaller than range start (%d)\n",
15859 end, start);
15860 return CLI_FAILURE;
15861 }
15863 return CLI_SUCCESS;
15864}
static void dahdi_destroy_channel_range(int start, int end)
Definition: chan_dahdi.c:11538

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

14187{
14188#if defined(HAVE_PRI)
14189 const char *device;
14190 unsigned span;
14191 int res;
14192
14193 device = data;
14194
14195 if (*device != 'I') {
14196 /* The request is not for an ISDN span device. */
14197 return AST_DEVICE_UNKNOWN;
14198 }
14199 res = sscanf(device, "I%30u", &span);
14200 if (res != 1 || !span || NUM_SPANS < span) {
14201 /* Bad format for ISDN span device name. */
14202 return AST_DEVICE_UNKNOWN;
14203 }
14204 device = strchr(device, '/');
14205 if (!device) {
14206 /* Bad format for ISDN span device name. */
14207 return AST_DEVICE_UNKNOWN;
14208 }
14209
14210 /*
14211 * Since there are currently no other span devstate's defined,
14212 * it must be congestion.
14213 */
14214#if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14215 ++device;
14216 if (!strcmp(device, "congestion"))
14217#endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14218 {
14219 return pris[span - 1].pri.congestion_devstate;
14220 }
14221#if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14222 else if (!strcmp(device, "threshold")) {
14223 return pris[span - 1].pri.threshold_devstate;
14224 }
14225 return AST_DEVICE_UNKNOWN;
14226#endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14227#else
14228 return AST_DEVICE_UNKNOWN;
14229#endif /* defined(HAVE_PRI) */
14230}
@ 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 1420 of file chan_dahdi.c.

1421{
1422 int res;
1423 int offset;
1424 const char *pos;
1425 struct dahdi_dialoperation zo = {
1426 .op = operation,
1427 };
1428
1429 /* Convert the W's to ww. */
1430 pos = dial_str;
1431 for (offset = 0; offset < sizeof(zo.dialstr) - 1; ++offset) {
1432 if (!*pos) {
1433 break;
1434 }
1435 if (*pos == 'W') {
1436 /* Convert 'W' to "ww" */
1437 ++pos;
1438 if (offset >= sizeof(zo.dialstr) - 3) {
1439 /* No room to expand */
1440 break;
1441 }
1442 zo.dialstr[offset] = 'w';
1443 ++offset;
1444 zo.dialstr[offset] = 'w';
1445 continue;
1446 }
1447 zo.dialstr[offset] = *pos++;
1448 }
1449 /* The zo initialization has already terminated the dialstr. */
1450
1451 ast_debug(1, "Channel %d: Dial str '%s' expanded to '%s' sent to DAHDI_DIAL.\n",
1452 pvt->channel, dial_str, zo.dialstr);
1453 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
1454 if (res) {
1455 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
1456 pvt->channel, dial_str, strerror(errno));
1457 }
1458
1459 return res;
1460}

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

4568{
4569 struct dahdi_pvt *pvt;
4570 int idx;
4571 int dtmf;
4572 int res;
4573
4574 pvt = ast_channel_tech_pvt(chan);
4575
4576 ast_mutex_lock(&pvt->lock);
4577
4578 idx = dahdi_get_index(chan, pvt, 0);
4579
4580 if ((idx != SUB_REAL) || !pvt->owner)
4581 goto out;
4582
4583#ifdef HAVE_PRI
4584 switch (pvt->sig) {
4586 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
4587 if (!res)
4588 goto out;
4589 break;
4590 default:
4591 break;
4592 }
4593#endif
4594 dtmf = digit_to_dtmfindex(digit);
4595 if (dtmf == -1) {
4596 /* Not a valid DTMF digit */
4597 goto out;
4598 }
4599
4600 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
4601 char dial_str[] = { 'T', digit, '\0' };
4602
4603 res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
4604 if (!res) {
4605 pvt->dialing = 1;
4606 }
4607 } else {
4608 pvt->dialing = 1;
4609 pvt->begindigit = digit;
4610
4611 /* Flush the write buffer in DAHDI to start sending the digit immediately. */
4612 dtmf = DAHDI_FLUSH_WRITE;
4613 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &dtmf);
4614 if (res) {
4615 ast_log(LOG_WARNING, "Unable to flush the DAHDI write buffer to send DTMF on channel %d: %s\n",
4616 pvt->channel, strerror(errno));
4617 }
4618
4619 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
4620 ast_channel_name(chan), digit);
4621 }
4622
4623out:
4624 ast_mutex_unlock(&pvt->lock);
4625
4626 return 0;
4627}
char digit
static int digit_to_dtmfindex(char digit)
Definition: chan_dahdi.c:4551
static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
Definition: chan_dahdi.c:1420
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:358
char begindigit
DTMF digit in progress. 0 when no digit in progress.
Definition: chan_dahdi.h:767

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

4630{
4631 struct dahdi_pvt *pvt;
4632 int res = 0;
4633 int idx;
4634 int x;
4635
4636 pvt = ast_channel_tech_pvt(chan);
4637
4638 ast_mutex_lock(&pvt->lock);
4639
4640 idx = dahdi_get_index(chan, pvt, 0);
4641
4642 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
4643 goto out;
4644
4645#ifdef HAVE_PRI
4646 /* This means that the digit was already sent via PRI signalling */
4647 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
4648 goto out;
4649 }
4650#endif
4651
4652 if (pvt->begindigit) {
4653 x = -1;
4654 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
4655 ast_channel_name(chan), digit);
4656 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
4657 pvt->dialing = 0;
4658 pvt->begindigit = 0;
4659 }
4660
4661out:
4662 ast_mutex_unlock(&pvt->lock);
4663
4664 return res;
4665}

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

9937{
9938 if (dahdi_analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
9939 return analog_dnd(dahdichan->sig_pvt, flag);
9940 }
9941
9942 if (flag == -1) {
9943 return dahdichan->dnd;
9944 }
9945
9946 /* Do not disturb */
9947 dahdichan->dnd = flag;
9948 ast_verb(3, "%s DND on channel %d\n",
9949 flag? "Enabled" : "Disabled",
9950 dahdichan->channel);
9951 publish_dnd_state(dahdichan->channel, flag ? "enabled" : "disabled");
9952 return 0;
9953}
static void publish_dnd_state(int channel, const char *status)
Definition: chan_dahdi.c:9907
long int flag
Definition: f2c.h:83
int analog_dnd(struct analog_pvt *p, int flag)
Definition: sig_analog.c:4407
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 6833 of file chan_dahdi.c.

6834{
6835 int val = 0;
6836
6837 p->ignoredtmf = 1;
6838
6839 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6840
6841 if (!p->hardwaredtmf && p->dsp) {
6842 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
6844 }
6845}
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:744
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 6847 of file chan_dahdi.c.

6848{
6849 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
6850
6851 if (p->channel == CHAN_PSEUDO)
6852 return;
6853
6854 p->ignoredtmf = 0;
6855
6856 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6857
6858 if (!p->hardwaredtmf && p->dsp) {
6861 }
6862}
#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 5040 of file chan_dahdi.c.

5041{
5042 int res;
5043
5044 if (p->echocanon) {
5045 struct dahdi_echocanparams ecp = { .tap_length = 0 };
5046
5047 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
5048
5049 if (res)
5050 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
5051 else
5052 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
5053 }
5054
5055 p->echocanon = 0;
5056}
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 4968 of file chan_dahdi.c.

4969{
4970 int res;
4971 if (!p)
4972 return;
4973 if (p->echocanon) {
4974 ast_debug(1, "Echo cancellation already on\n");
4975 return;
4976 }
4977 if (p->digital) {
4978 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
4979 return;
4980 }
4981 if (p->echocancel.head.tap_length) {
4982#if defined(HAVE_PRI) || defined(HAVE_SS7)
4983 switch (p->sig) {
4984#if defined(HAVE_PRI)
4986 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
4987 /*
4988 * PRI nobch pseudo channel. Does not need ec anyway.
4989 * Does not handle ioctl(DAHDI_AUDIOMODE)
4990 */
4991 return;
4992 }
4993 /* Fall through */
4994#endif /* defined(HAVE_PRI) */
4995#if defined(HAVE_SS7)
4996 case SIG_SS7:
4997#endif /* defined(HAVE_SS7) */
4998 {
4999 int x = 1;
5000
5001 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
5002 if (res)
5004 "Unable to enable audio mode on channel %d (%s)\n",
5005 p->channel, strerror(errno));
5006 }
5007 break;
5008 default:
5009 break;
5010 }
5011#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
5012 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
5013 if (res) {
5014 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
5015 } else {
5016 p->echocanon = 1;
5017 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
5018 }
5019 } else
5020 ast_debug(1, "No echo cancellation requested\n");
5021}
struct dahdi_pvt::@115 echocancel
Echo cancel parameters.
struct dahdi_echocanparams head
Definition: chan_dahdi.h:633
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 8843 of file chan_dahdi.c.

8844{
8845 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8846 struct ast_frame *f;
8847 ast_mutex_lock(&p->lock);
8848 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8849 struct analog_pvt *analog_p = p->sig_pvt;
8850 f = analog_exception(analog_p, ast);
8851 } else {
8852 f = __dahdi_exception(ast);
8853 }
8855 return f;
8856}
static struct ast_frame * __dahdi_exception(struct ast_channel *ast)
Definition: chan_dahdi.c:8721
struct ast_frame * analog_exception(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:3914

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

16842{
16843 if (p) {
16844 switch (mode) {
16845 case TRANSFER:
16846 p->fake_event = DAHDI_EVENT_WINKFLASH;
16847 break;
16848 case HANGUP:
16849 p->fake_event = DAHDI_EVENT_ONHOOK;
16850 break;
16851 default:
16852 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));
16853 }
16854 }
16855 return 0;
16856}

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

7495{
7496 struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
7497 int x;
7498
7499 ast_mutex_lock(&p->lock);
7500
7501 ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
7502 if (p->owner == oldchan) {
7503 p->owner = newchan;
7504 }
7505 for (x = 0; x < 3; x++) {
7506 if (p->subs[x].owner == oldchan) {
7507 if (!x) {
7509 }
7510 p->subs[x].owner = newchan;
7511 }
7512 }
7513 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
7514 analog_fixup(oldchan, newchan, p->sig_pvt);
7515#if defined(HAVE_PRI)
7516 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
7517 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
7518#endif /* defined(HAVE_PRI) */
7519#if defined(HAVE_SS7)
7520 } else if (p->sig == SIG_SS7) {
7521 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
7522#endif /* defined(HAVE_SS7) */
7523 }
7525
7527
7528 if (ast_channel_state(newchan) == AST_STATE_RINGING) {
7530 }
7531 return 0;
7532}
static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Definition: chan_dahdi.c:9442
void dahdi_master_slave_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
Definition: chan_dahdi.c:7414
@ AST_CONTROL_RINGING
int analog_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, void *newp)
Definition: sig_analog.c:4369
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 7132 of file chan_dahdi.c.

7133{
7134 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
7135 int res = 0;
7136
7137 if (!p) {
7138 /* No private structure! */
7139 *buf = '\0';
7140 return -1;
7141 }
7142
7143 if (!strcasecmp(data, "rxgain")) {
7144 ast_mutex_lock(&p->lock);
7145 snprintf(buf, len, "%f", p->rxgain);
7147 } else if (!strcasecmp(data, "txgain")) {
7148 ast_mutex_lock(&p->lock);
7149 snprintf(buf, len, "%f", p->txgain);
7151 } else if (!strcasecmp(data, "dahdi_channel")) {
7152 ast_mutex_lock(&p->lock);
7153 snprintf(buf, len, "%d", p->channel);
7155 } else if (!strcasecmp(data, "dahdi_span")) {
7156 ast_mutex_lock(&p->lock);
7157 snprintf(buf, len, "%d", p->span);
7159 } else if (!strcasecmp(data, "dahdi_group")) {
7160 ast_mutex_lock(&p->lock);
7161 snprintf(buf, len, "%llu", p->group);
7163 } else if (!strcasecmp(data, "dahdi_type")) {
7164 ast_mutex_lock(&p->lock);
7165 switch (p->sig) {
7166#if defined(HAVE_OPENR2)
7167 case SIG_MFCR2:
7168 ast_copy_string(buf, "mfc/r2", len);
7169 break;
7170#endif /* defined(HAVE_OPENR2) */
7171#if defined(HAVE_PRI)
7173 ast_copy_string(buf, "pri", len);
7174 break;
7175#endif /* defined(HAVE_PRI) */
7176 case 0:
7177 ast_copy_string(buf, "pseudo", len);
7178 break;
7179#if defined(HAVE_SS7)
7180 case SIG_SS7:
7181 ast_copy_string(buf, "ss7", len);
7182 break;
7183#endif /* defined(HAVE_SS7) */
7184 default:
7185 /* The only thing left is analog ports. */
7186 ast_copy_string(buf, "analog", len);
7187 break;
7188 }
7190#if defined(HAVE_PRI)
7191#if defined(HAVE_PRI_REVERSE_CHARGE)
7192 } else if (!strcasecmp(data, "reversecharge")) {
7193 ast_mutex_lock(&p->lock);
7194 switch (p->sig) {
7196 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
7197 break;
7198 default:
7199 *buf = '\0';
7200 res = -1;
7201 break;
7202 }
7204#endif
7205#if defined(HAVE_PRI_SETUP_KEYPAD)
7206 } else if (!strcasecmp(data, "keypad_digits")) {
7207 ast_mutex_lock(&p->lock);
7208 switch (p->sig) {
7210 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
7211 len);
7212 break;
7213 default:
7214 *buf = '\0';
7215 res = -1;
7216 break;
7217 }
7219#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
7220 } else if (!strcasecmp(data, "no_media_path")) {
7221 ast_mutex_lock(&p->lock);
7222 switch (p->sig) {
7224 /*
7225 * TRUE if the call is on hold or is call waiting because
7226 * there is no media path available.
7227 */
7228 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
7229 break;
7230 default:
7231 *buf = '\0';
7232 res = -1;
7233 break;
7234 }
7236#endif /* defined(HAVE_PRI) */
7237 } else if (!strcasecmp(data, "dialmode")) {
7238 struct analog_pvt *analog_p;
7239 ast_mutex_lock(&p->lock);
7240 analog_p = p->sig_pvt;
7241 /* Hardcode p->radio and p->oprmode as 0 since we're using this to check for analogness, not the handler */
7242 if (dahdi_analog_lib_handles(p->sig, 0, 0) && analog_p) {
7243 switch (analog_p->dialmode) {
7245 ast_copy_string(buf, "both", len);
7246 break;
7248 ast_copy_string(buf, "pulse", len);
7249 break;
7251 ast_copy_string(buf, "dtmf", len);
7252 break;
7254 ast_copy_string(buf, "none", len);
7255 break;
7256 }
7257 } else {
7258 ast_log(LOG_WARNING, "%s only supported on analog channels\n", data);
7259 *buf = '\0';
7260 res = -1;
7261 }
7263 } else {
7264 *buf = '\0';
7265 res = -1;
7266 }
7267
7268 return res;
7269}
@ 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:323

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

7302{
7303 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
7304 int res = 0;
7305
7306 if (!p) {
7307 /* No private structure! */
7308 return -1;
7309 }
7310
7311 if (!strcasecmp(data, "buffers")) {
7312 int num_bufs, policy;
7313
7314 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
7315 struct dahdi_bufferinfo bi = {
7316 .txbufpolicy = policy,
7317 .rxbufpolicy = policy,
7318 .bufsize = p->bufsize,
7319 .numbufs = num_bufs,
7320 };
7321 int bpres;
7322
7323 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7324 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
7325 } else {
7326 p->bufferoverrideinuse = 1;
7327 }
7328 } else {
7329 res = -1;
7330 }
7331 } else if (!strcasecmp(data, "echocan_mode")) {
7332 if (!strcasecmp(value, "on")) {
7333 ast_mutex_lock(&p->lock);
7334 dahdi_ec_enable(p);
7336 } else if (!strcasecmp(value, "off")) {
7337 ast_mutex_lock(&p->lock);
7340#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7341 } else if (!strcasecmp(value, "fax")) {
7342 int blah = 1;
7343
7344 ast_mutex_lock(&p->lock);
7345 if (!p->echocanon) {
7346 dahdi_ec_enable(p);
7347 }
7348 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
7349 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
7350 }
7352 } else if (!strcasecmp(value, "voice")) {
7353 int blah = 0;
7354
7355 ast_mutex_lock(&p->lock);
7356 if (!p->echocanon) {
7357 dahdi_ec_enable(p);
7358 }
7359 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
7360 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
7361 }
7363#endif
7364 } else {
7365 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
7366 res = -1;
7367 }
7368 } else if (!strcasecmp(data, "dialmode")) {
7369 struct analog_pvt *analog_p;
7370
7371 ast_mutex_lock(&p->lock);
7372 analog_p = p->sig_pvt;
7373 if (!dahdi_analog_lib_handles(p->sig, 0, 0) || !analog_p) {
7374 ast_log(LOG_WARNING, "%s only supported on analog channels\n", data);
7376 return -1;
7377 }
7378 /* analog pvt is used for pulse dialing, so update both */
7379 if (!strcasecmp(value, "pulse")) {
7380 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_PULSE;
7381 } else if (!strcasecmp(value, "dtmf") || !strcasecmp(value, "tone")) {
7382 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_DTMF;
7383 } else if (!strcasecmp(value, "none")) {
7384 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_NONE;
7385 } else if (!strcasecmp(value, "both")) {
7386 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_BOTH;
7387 } else {
7388 ast_log(LOG_WARNING, "'%s' is an invalid setting for %s\n", value, data);
7389 res = -1;
7390 }
7392 } else if (!strcasecmp(data, "waitfordialtone")) {
7393 if (ast_strlen_zero(value)) {
7394 ast_log(LOG_WARNING, "waitfordialtone requires a duration in ms\n");
7395 return -1;
7396 }
7397
7398 ast_mutex_lock(&p->lock);
7399 if (!CANPROGRESSDETECT(p)) {
7400 ast_log(LOG_WARNING, "%s only supported on analog trunks\n", data);
7402 return -1;
7403 }
7404 /* Only set the temp waitfordialtone setting, not the permanent one. */
7405 p->waitfordialtonetemp = atoi(value);
7407 } else {
7408 res = -1;
7409 }
7410
7411 return res;
7412}
#define CANPROGRESSDETECT(p)
Definition: chan_dahdi.c:785
static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
Definition: chan_dahdi.c:7272
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:666
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 843 of file chan_dahdi.c.

844{
845 int j;
846 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
847 return -1;
848 return j;
849}

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

7665{
7666 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7667 struct ast_frame *f = *dest;
7668
7669 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
7670 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
7671 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
7672
7673 if (p->confirmanswer) {
7674 if (f->frametype == AST_FRAME_DTMF_END) {
7675 ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
7676 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
7677 of a DTMF digit */
7680 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
7681 p->confirmanswer = 0;
7682 } else {
7683 p->subs[idx].f.frametype = AST_FRAME_NULL;
7684 p->subs[idx].f.subclass.integer = 0;
7685 }
7686 *dest = &p->subs[idx].f;
7687 } else if (p->callwaitcas) {
7688 if (f->frametype == AST_FRAME_DTMF_END) {
7689 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
7690 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
7691 ast_free(p->cidspill);
7692 p->cidspill = NULL;
7693 send_cwcidspill(p);
7694 }
7695 p->callwaitcas = 0;
7696 }
7697 p->subs[idx].f.frametype = AST_FRAME_NULL;
7698 p->subs[idx].f.subclass.integer = 0;
7699 *dest = &p->subs[idx].f;
7700 } else if (f->subclass.integer == 'f') {
7701 if (f->frametype == AST_FRAME_DTMF_END) {
7702 /* Fax tone -- Handle and return NULL */
7703 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
7704 /* If faxbuffers are configured, use them for the fax transmission */
7705 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
7706 struct dahdi_bufferinfo bi = {
7707 .txbufpolicy = p->faxbuf_policy,
7708 .bufsize = p->bufsize,
7709 .numbufs = p->faxbuf_no
7710 };
7711 int res;
7712
7713 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7714 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
7715 } else {
7716 p->bufferoverrideinuse = 1;
7717 }
7718 }
7719 p->faxhandled = 1;
7720 if (p->dsp) {
7721 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
7723 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
7724 }
7725 if (strcmp(ast_channel_exten(ast), "fax")) {
7726 const char *target_context = ast_channel_context(ast);
7727
7728 /*
7729 * We need to unlock 'ast' here because ast_exists_extension has the
7730 * potential to start autoservice on the channel. Such action is prone
7731 * to deadlock if the channel is locked.
7732 *
7733 * ast_async_goto() has its own restriction on not holding the
7734 * channel lock.
7735 */
7737 ast_channel_unlock(ast);
7738 if (ast_exists_extension(ast, target_context, "fax", 1,
7739 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
7740 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
7741 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
7742 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
7743 if (ast_async_goto(ast, target_context, "fax", 1))
7744 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
7745 } else {
7746 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
7747 }
7748 ast_channel_lock(ast);
7749 ast_mutex_lock(&p->lock);
7750 } else {
7751 ast_debug(1, "Already in a fax extension, not redirecting\n");
7752 }
7753 } else {
7754 ast_debug(1, "Fax already handled\n");
7755 }
7756 dahdi_confmute(p, 0);
7757 }
7758 p->subs[idx].f.frametype = AST_FRAME_NULL;
7759 p->subs[idx].f.subclass.integer = 0;
7760 *dest = &p->subs[idx].f;
7761 }
7762}
static int dahdi_confmute(struct dahdi_pvt *p, int muted)
Definition: chan_dahdi.c:5269
#define CALLPROGRESS_FAX
Definition: chan_dahdi.c:752
static int send_cwcidspill(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5347
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:6984
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:657
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 7819 of file chan_dahdi.c.

7820{
7821 int res, x;
7822 int idx, mysig;
7823 char *c;
7824 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7825 pthread_t threadid;
7826 struct ast_channel *chan;
7827 struct ast_frame *f;
7828
7829 idx = dahdi_get_index(ast, p, 0);
7830 if (idx < 0) {
7831 return &ast_null_frame;
7832 }
7833 mysig = p->sig;
7834 if (p->outsigmod > -1)
7835 mysig = p->outsigmod;
7836 p->subs[idx].f.frametype = AST_FRAME_NULL;
7837 p->subs[idx].f.subclass.integer = 0;
7838 p->subs[idx].f.datalen = 0;
7839 p->subs[idx].f.samples = 0;
7840 p->subs[idx].f.mallocd = 0;
7841 p->subs[idx].f.offset = 0;
7842 p->subs[idx].f.src = "dahdi_handle_event";
7843 p->subs[idx].f.data.ptr = NULL;
7844 f = &p->subs[idx].f;
7845
7846 if (p->fake_event) {
7847 res = p->fake_event;
7848 p->fake_event = 0;
7849 } else
7850 res = dahdi_get_event(p->subs[idx].dfd);
7851
7852 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
7853
7854 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
7855 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
7856 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
7857#if defined(HAVE_PRI)
7859 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
7860 && p->pri
7861 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7862 /* absorb event */
7863 } else
7864#endif /* defined(HAVE_PRI) */
7865 {
7866 /* Unmute conference */
7867 dahdi_confmute(p, 0);
7869 p->subs[idx].f.subclass.integer = res & 0xff;
7870 dahdi_handle_dtmf(ast, idx, &f);
7871 }
7872 return f;
7873 }
7874
7875 if (res & DAHDI_EVENT_DTMFDOWN) {
7876 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
7877#if defined(HAVE_PRI)
7879 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
7880 && p->pri
7881 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7882 /* absorb event */
7883 } else
7884#endif /* defined(HAVE_PRI) */
7885 {
7886 /* Mute conference */
7887 dahdi_confmute(p, 1);
7889 p->subs[idx].f.subclass.integer = res & 0xff;
7890 dahdi_handle_dtmf(ast, idx, &f);
7891 }
7892 return &p->subs[idx].f;
7893 }
7894
7895 switch (res) {
7896 case DAHDI_EVENT_EC_DISABLED:
7897 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
7898 p->echocanon = 0;
7899 break;
7900#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7901 case DAHDI_EVENT_TX_CED_DETECTED:
7902 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
7903 break;
7904 case DAHDI_EVENT_RX_CED_DETECTED:
7905 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
7906 break;
7907 case DAHDI_EVENT_EC_NLP_DISABLED:
7908 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
7909 break;
7910 case DAHDI_EVENT_EC_NLP_ENABLED:
7911 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
7912 break;
7913#endif
7914 case DAHDI_EVENT_BITSCHANGED:
7915#ifdef HAVE_OPENR2
7916 if (p->sig != SIG_MFCR2) {
7917 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
7918 } else {
7919 ast_debug(1, "bits changed in chan %d\n", p->channel);
7920 openr2_chan_handle_cas(p->r2chan);
7921 }
7922#else
7923 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
7924#endif
7925 break;
7926 case DAHDI_EVENT_PULSE_START:
7927 /* Stop tone if there's a pulse start and the PBX isn't started */
7928 if (!ast_channel_pbx(ast))
7929 tone_zone_play_tone(p->subs[idx].dfd, -1);
7930 break;
7931 case DAHDI_EVENT_DIALCOMPLETE:
7932 /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
7933#if defined(HAVE_PRI)
7935 if (p->inalarm) {
7936 break;
7937 }
7938 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
7939 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",
7940 ast_channel_name(ast), strerror(errno));
7941 return NULL;
7942 }
7943 if (x) {
7944 /* Still dialing in DAHDI driver */
7945 break;
7946 }
7947 /*
7948 * The ast channel is locked and the private may be locked more
7949 * than once.
7950 */
7952 break;
7953 }
7954#endif /* defined(HAVE_PRI) */
7955#ifdef HAVE_OPENR2
7956 if ((p->sig & SIG_MFCR2) && p->r2chan && ast_channel_state(ast) != AST_STATE_UP) {
7957 /* we don't need to do anything for this event for R2 signaling
7958 if the call is being setup */
7959 break;
7960 }
7961#endif
7962 if (p->inalarm) break;
7963 if ((p->radio || (p->oprmode < 0))) break;
7964 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
7965 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
7966 return NULL;
7967 }
7968 if (!x) { /* if not still dialing in driver */
7969 dahdi_ec_enable(p);
7970 if (p->echobreak) {
7971 dahdi_train_ec(p);
7972 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
7973 p->dop.op = DAHDI_DIAL_OP_REPLACE;
7974 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
7975 p->echobreak = 0;
7976 } else {
7977 p->dialing = 0;
7978 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
7979 /* if thru with dialing after offhook */
7984 break;
7985 } else { /* if to state wait for offhook to dial rest */
7986 /* we now wait for off hook */
7988 }
7989 }
7991 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
7992 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
7993 } else if (p->confirmanswer || (!p->dialednone
7994 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
7995 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
7996 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
7997 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
7998 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
7999 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
8000 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
8001 || (mysig == SIG_SF_FEATB)))) {
8003 } else if (!p->answeronpolarityswitch) {
8007 /* If aops=0 and hops=1, this is necessary */
8009 } else {
8010 /* Start clean, so we can catch the change to REV polarity when party answers */
8012 }
8013 }
8014 }
8015 }
8016 break;
8017 case DAHDI_EVENT_ALARM:
8018 switch (p->sig) {
8019#if defined(HAVE_PRI)
8022 break;
8023#endif /* defined(HAVE_PRI) */
8024#if defined(HAVE_SS7)
8025 case SIG_SS7:
8027 break;
8028#endif /* defined(HAVE_SS7) */
8029 default:
8030 p->inalarm = 1;
8031 break;
8032 }
8033 res = get_alarms(p);
8034 handle_alarms(p, res);
8035#ifdef HAVE_PRI
8036 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
8037 /* fall through intentionally */
8038 } else {
8039 break;
8040 }
8041#endif
8042#if defined(HAVE_SS7)
8043 if (p->sig == SIG_SS7)
8044 break;
8045#endif /* defined(HAVE_SS7) */
8046#ifdef HAVE_OPENR2
8047 if (p->sig == SIG_MFCR2)
8048 break;
8049#endif
8050 case DAHDI_EVENT_ONHOOK:
8051 if (p->radio) {
8054 break;
8055 }
8056 if (p->oprmode < 0)
8057 {
8058 if (p->oprmode != -1) { /* Operator flash recall */
8059 ast_verb(4, "Operator mode enabled on channel %d, holding line for channel %d\n", p->channel, p->oprpeer->channel);
8060 break;
8061 }
8062 /* Otherwise, immediate recall */
8063 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
8064 {
8065 /* Make sure it starts ringing */
8066 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
8067 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
8069 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
8070 ast_verb(4, "Operator recall, channel %d ringing back channel %d\n", p->oprpeer->channel, p->channel);
8071 }
8072 break;
8073 }
8074 switch (p->sig) {
8075 case SIG_FXOLS:
8076 case SIG_FXOGS:
8077 case SIG_FXOKS:
8078 /* Check for some special conditions regarding call waiting */
8079 if (idx == SUB_REAL) {
8080 /* The normal line was hung up */
8081 if (p->subs[SUB_CALLWAIT].owner) {
8082 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
8084 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
8086#if 0
8087 p->subs[idx].needanswer = 0;
8088 p->subs[idx].needringing = 0;
8089#endif
8090 p->callwaitingrepeat = 0;
8091 p->cidcwexpire = 0;
8092 p->cid_suppress_expire = 0;
8093 p->owner = NULL;
8094 /* Don't start streaming audio yet if the incoming call isn't up yet */
8096 p->dialing = 1;
8098 } else if (p->subs[SUB_THREEWAY].owner) {
8099 unsigned int mssinceflash;
8100 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
8101 the private structure -- not especially easy or clean */
8103 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
8104 DLA_UNLOCK(&p->lock);
8106 /* We can grab ast and p in that order, without worry. We should make sure
8107 nothing seriously bad has happened though like some sort of bizarre double
8108 masquerade! */
8109 DLA_LOCK(&p->lock);
8110 if (p->owner != ast) {
8111 ast_log(LOG_WARNING, "This isn't good...\n");
8112 return NULL;
8113 }
8114 }
8115 if (!p->subs[SUB_THREEWAY].owner) {
8116 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
8117 return NULL;
8118 }
8119 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
8120 ast_debug(1, "Last flash was %u ms ago\n", mssinceflash);
8121 if (mssinceflash < MIN_MS_SINCE_FLASH) {
8122 /* It hasn't been long enough since the last flashook. This is probably a bounce on
8123 hanging up. Hangup both channels now */
8124 if (p->subs[SUB_THREEWAY].owner)
8127 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
8129 } else if ((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) {
8130 if (p->transfer) {
8131 /* In any case this isn't a threeway call anymore */
8132 p->subs[SUB_REAL].inthreeway = 0;
8134 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
8135 if (!p->transfertobusy && ast_channel_state(ast) == AST_STATE_BUSY) {
8137 /* Swap subs and dis-own channel */
8139 p->owner = NULL;
8140 /* Ring the phone */
8142 } else if (!attempt_transfer(p)) {
8143 /*
8144 * Transfer successful. Don't actually hang up at this point.
8145 * Let our channel legs of the calls die off as the transfer
8146 * percolates through the core.
8147 */
8148 break;
8149 }
8150 } else {
8152 if (p->subs[SUB_THREEWAY].owner)
8154 }
8155 } else {
8157 /* Swap subs and dis-own channel */
8159 p->owner = NULL;
8160 /* Ring the phone */
8162 }
8163 }
8164 } else {
8165 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
8166 }
8167 /* Fall through */
8168 default:
8170 return NULL;
8171 }
8172 break;
8173 case DAHDI_EVENT_RINGOFFHOOK:
8174 if (p->inalarm) break;
8175 if (p->oprmode < 0)
8176 {
8177 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
8178 {
8179 /* Make sure it stops ringing */
8180 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
8181 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
8183 ast_debug(1, "Operator recall by channel %d for channel %d complete\n", p->oprpeer->channel, p->channel);
8184 }
8185 break;
8186 }
8187 if (p->radio)
8188 {
8191 break;
8192 }
8193 /* for E911, its supposed to wait for offhook then dial
8194 the second half of the dial string */
8195 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK)) {
8196 c = strchr(p->dialdest, '/');
8197 if (c)
8198 c++;
8199 else
8200 c = p->dialdest;
8201
8202 if (*c) {
8203 int numchars = snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
8204 if (numchars >= sizeof(p->dop.dialstr)) {
8205 ast_log(LOG_WARNING, "Dial string '%s' truncated\n", c);
8206 }
8207 } else {
8208 ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
8209 }
8210
8211 if (strlen(p->dop.dialstr) > 4) {
8212 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
8213 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
8214 p->echorest[sizeof(p->echorest) - 1] = '\0';
8215 p->echobreak = 1;
8216 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
8217 } else
8218 p->echobreak = 0;
8219 if (dahdi_dial_str(p, p->dop.op, p->dop.dialstr)) {
8220 x = DAHDI_ONHOOK;
8221 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
8222 return NULL;
8223 }
8224 p->dialing = 1;
8225 return &p->subs[idx].f;
8226 }
8227 switch (p->sig) {
8228 case SIG_FXOLS:
8229 case SIG_FXOGS:
8230 case SIG_FXOKS:
8231 switch (ast_channel_state(ast)) {
8232 case AST_STATE_RINGING:
8233 dahdi_ec_enable(p);
8234 dahdi_train_ec(p);
8237 /* Make sure it stops ringing */
8238 p->subs[SUB_REAL].needringing = 0;
8239 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
8240 ast_debug(1, "channel %d answered\n", p->channel);
8241
8242 /* Cancel any running CallerID spill */
8243 ast_free(p->cidspill);
8244 p->cidspill = NULL;
8246
8247 p->dialing = 0;
8248 p->callwaitcas = 0;
8249 if (p->confirmanswer) {
8250 /* Ignore answer if "confirm answer" is enabled */
8251 p->subs[idx].f.frametype = AST_FRAME_NULL;
8252 p->subs[idx].f.subclass.integer = 0;
8253 } else if (!ast_strlen_zero(p->dop.dialstr)) {
8254 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
8255 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8256 if (res) {
8257 p->dop.dialstr[0] = '\0';
8258 return NULL;
8259 } else {
8260 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
8261 p->subs[idx].f.frametype = AST_FRAME_NULL;
8262 p->subs[idx].f.subclass.integer = 0;
8263 p->dialing = 1;
8264 }
8265 p->dop.dialstr[0] = '\0';
8267 } else
8269 return &p->subs[idx].f;
8270 case AST_STATE_DOWN:
8272 ast_channel_rings_set(ast, 1);
8275 ast_debug(1, "channel %d picked up\n", p->channel);
8276 return &p->subs[idx].f;
8277 case AST_STATE_UP:
8278 /* Make sure it stops ringing */
8279 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
8280 /* Okay -- probably call waiting*/
8282 p->subs[idx].needunhold = 1;
8283 break;
8284 case AST_STATE_RESERVED:
8285 /* Start up dialtone */
8286 if (has_voicemail(p))
8287 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
8288 else
8289 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
8290 break;
8291 default:
8292 ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast_channel_state(ast));
8293 }
8294 break;
8295 case SIG_FXSLS:
8296 case SIG_FXSGS:
8297 case SIG_FXSKS:
8298 if (ast_channel_state(ast) == AST_STATE_RING) {
8299 p->ringt = p->ringt_base;
8300 }
8301
8302 /* If we get a ring then we cannot be in
8303 * reversed polarity. So we reset to idle */
8304 ast_debug(1, "Setting IDLE polarity due "
8305 "to ring. Old polarity was %d\n",
8306 p->polarity);
8308
8309 /* Fall through */
8310 case SIG_EM:
8311 case SIG_EM_E1:
8312 case SIG_EMWINK:
8313 case SIG_FEATD:
8314 case SIG_FEATDMF:
8315 case SIG_FEATDMF_TA:
8316 case SIG_E911:
8317 case SIG_FGC_CAMA:
8318 case SIG_FGC_CAMAMF:
8319 case SIG_FEATB:
8320 case SIG_SF:
8321 case SIG_SFWINK:
8322 case SIG_SF_FEATD:
8323 case SIG_SF_FEATDMF:
8324 case SIG_SF_FEATB:
8328 ast_debug(1, "Ring detected\n");
8331 } else if (p->outgoing && ((ast_channel_state(ast) == AST_STATE_RINGING) || (ast_channel_state(ast) == AST_STATE_DIALING))) {
8332 ast_debug(1, "Line answered\n");
8333 if (p->confirmanswer) {
8334 p->subs[idx].f.frametype = AST_FRAME_NULL;
8335 p->subs[idx].f.subclass.integer = 0;
8336 } else {
8340 }
8341 } else if (ast_channel_state(ast) != AST_STATE_RING)
8342 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast_channel_state(ast), p->channel);
8343 break;
8344 default:
8345 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
8346 }
8347 break;
8348 case DAHDI_EVENT_RINGBEGIN:
8349 switch (p->sig) {
8350 case SIG_FXSLS:
8351 case SIG_FXSGS:
8352 case SIG_FXSKS:
8353 if (ast_channel_state(ast) == AST_STATE_RING) {
8354 p->ringt = p->ringt_base;
8355 }
8356 break;
8357 }
8358 break;
8359 case DAHDI_EVENT_RINGERON:
8360 break;
8361 case DAHDI_EVENT_NOALARM:
8362 switch (p->sig) {
8363#if defined(HAVE_PRI)
8366 break;
8367#endif /* defined(HAVE_PRI) */
8368#if defined(HAVE_SS7)
8369 case SIG_SS7:
8371 break;
8372#endif /* defined(HAVE_SS7) */
8373 default:
8374 p->inalarm = 0;
8375 break;
8376 }
8378 break;
8379 case DAHDI_EVENT_WINKFLASH:
8380 if (p->inalarm) break;
8381 if (p->radio) break;
8382 if (p->oprmode < 0) break;
8383 if (p->oprmode > 1)
8384 {
8385 struct dahdi_params par;
8386
8387 memset(&par, 0, sizeof(par));
8388 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
8389 {
8390 if (!par.rxisoffhook)
8391 {
8392 /* Make sure it stops ringing */
8393 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
8394 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
8395 save_conference(p);
8396 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
8397 ast_verb(4, "Operator flash recall, channel %d ringing back channel %d\n", p->oprpeer->channel, p->channel);
8398 }
8399 }
8400 break;
8401 }
8402 /* Remember last time we got a flash-hook */
8403 p->flashtime = ast_tvnow();
8404 switch (mysig) {
8405 case SIG_FXOLS:
8406 case SIG_FXOGS:
8407 case SIG_FXOKS:
8408 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
8410
8411 /* Cancel any running CallerID spill */
8412 ast_free(p->cidspill);
8413 p->cidspill = NULL;
8415 p->callwaitcas = 0;
8416
8417 if (idx != SUB_REAL) {
8418 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
8419 goto winkflashdone;
8420 }
8421
8422 if (p->subs[SUB_CALLWAIT].owner) {
8423 /* Swap to call-wait */
8425 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
8426 p->owner = p->subs[SUB_REAL].owner;
8427 ast_debug(1, "Making %s the new owner\n", ast_channel_name(p->owner));
8430 p->subs[SUB_REAL].needanswer = 1;
8431 }
8432 p->callwaitingrepeat = 0;
8433 p->cidcwexpire = 0;
8434 p->cid_suppress_expire = 0;
8435 /* Start music on hold if appropriate */
8436 if (!p->subs[SUB_CALLWAIT].inthreeway) {
8438 }
8439 p->subs[SUB_CALLWAIT].needhold = 1;
8441 p->subs[SUB_REAL].needunhold = 1;
8442 } else if (!p->subs[SUB_THREEWAY].owner) {
8443 if (!p->threewaycalling) {
8444 /* Just send a flash if no 3-way calling */
8445 p->subs[SUB_REAL].needflash = 1;
8446 goto winkflashdone;
8447 } else if (!check_for_conference(p)) {
8448 ast_callid callid = 0;
8449 int callid_created;
8450 char cid_num[256];
8451 char cid_name[256];
8452
8453 cid_num[0] = 0;
8454 cid_name[0] = 0;
8455 if (p->dahditrcallerid && p->owner) {
8459 sizeof(cid_num));
8460 }
8464 sizeof(cid_name));
8465 }
8466 }
8467 /* XXX This section needs much more error checking!!! XXX */
8468 /* Start a 3-way call if feasible */
8469 if (!((ast_channel_pbx(ast)) ||
8470 (ast_channel_state(ast) == AST_STATE_UP) ||
8471 (ast_channel_state(ast) == AST_STATE_RING))) {
8472 ast_debug(1, "Flash when call not up or ringing\n");
8473 goto winkflashdone;
8474 }
8475 if (alloc_sub(p, SUB_THREEWAY)) {
8476 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
8477 goto winkflashdone;
8478 }
8479 callid_created = ast_callid_threadstorage_auto(&callid);
8480 /*
8481 * Make new channel
8482 *
8483 * We cannot hold the p or ast locks while creating a new
8484 * channel.
8485 */
8487 ast_channel_unlock(ast);
8488 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL, NULL, callid);
8489 ast_channel_lock(ast);
8490 ast_mutex_lock(&p->lock);
8491 if (p->dahditrcallerid) {
8492 if (!p->origcid_num)
8494 if (!p->origcid_name)
8496 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
8497 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
8498 }
8499 /* Swap things around between the three-way and real call */
8501 /* Disable echo canceller for better dialing */
8503 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
8504 if (res)
8505 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
8506 p->owner = chan;
8507 if (!chan) {
8508 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
8509 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
8510 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
8511 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
8512 dahdi_ec_enable(p);
8513 ast_hangup(chan);
8514 } else {
8515 ast_verb(3, "Started three way call on channel %d\n", p->channel);
8516
8517 /* Start music on hold */
8519 p->subs[SUB_THREEWAY].needhold = 1;
8520 }
8521 ast_callid_threadstorage_auto_clean(callid, callid_created);
8522 }
8523 } else {
8524 /* Already have a 3 way call */
8525 if (p->subs[SUB_THREEWAY].inthreeway) {
8526 /* Call is already up, drop the last person */
8527 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
8528 /* If the primary call isn't answered yet, use it */
8530 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
8532 p->owner = p->subs[SUB_REAL].owner;
8533 }
8534 /* Drop the last call and stop the conference */
8535 ast_verb(3, "Dropping three-way call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
8537 p->subs[SUB_REAL].inthreeway = 0;
8539 } else {
8540 /* Lets see what we're up to */
8541 if (((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) &&
8543 int otherindex = SUB_THREEWAY;
8544
8545 ast_verb(3, "Building conference call with %s and %s\n",
8548 /* Put them in the threeway, and flip */
8550 p->subs[SUB_REAL].inthreeway = 1;
8551 if (ast_channel_state(ast) == AST_STATE_UP) {
8553 otherindex = SUB_REAL;
8554 }
8555 if (p->subs[otherindex].owner) {
8556 ast_queue_unhold(p->subs[otherindex].owner);
8557 }
8558 p->subs[otherindex].needunhold = 1;
8559 p->owner = p->subs[SUB_REAL].owner;
8560 } else {
8561 ast_verb(3, "Dumping incomplete call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
8564 p->owner = p->subs[SUB_REAL].owner;
8565 if (p->subs[SUB_REAL].owner) {
8567 }
8568 p->subs[SUB_REAL].needunhold = 1;
8569 dahdi_ec_enable(p);
8570 }
8571 }
8572 }
8573winkflashdone:
8575 break;
8576 case SIG_EM:
8577 case SIG_EM_E1:
8578 case SIG_FEATD:
8579 case SIG_SF:
8580 case SIG_SFWINK:
8581 case SIG_SF_FEATD:
8582 case SIG_FXSLS:
8583 case SIG_FXSGS:
8584 if (p->dialing)
8585 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
8586 else
8587 ast_debug(1, "Got wink in weird state %u on channel %d\n", ast_channel_state(ast), p->channel);
8588 break;
8589 case SIG_FEATDMF_TA:
8590 switch (p->whichwink) {
8591 case 0:
8592 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", ast_channel_caller(p->owner)->ani2,
8595 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
8599 break;
8600 case 1:
8601 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
8602 break;
8603 case 2:
8604 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
8605 return NULL;
8606 }
8607 p->whichwink++;
8608 /* Fall through */
8609 case SIG_FEATDMF:
8610 case SIG_E911:
8611 case SIG_FGC_CAMAMF:
8612 case SIG_FGC_CAMA:
8613 case SIG_FEATB:
8614 case SIG_SF_FEATDMF:
8615 case SIG_SF_FEATB:
8616 case SIG_EMWINK:
8617 /* FGD MF and EMWINK *Must* wait for wink */
8618 if (!ast_strlen_zero(p->dop.dialstr)) {
8619 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8620 if (res) {
8621 p->dop.dialstr[0] = '\0';
8622 return NULL;
8623 } else
8624 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8625 }
8626 p->dop.dialstr[0] = '\0';
8627 break;
8628 default:
8629 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
8630 }
8631 break;
8632 case DAHDI_EVENT_HOOKCOMPLETE:
8633 if (p->inalarm) break;
8634 if ((p->radio || (p->oprmode < 0))) break;
8635 if (p->waitingfordt.tv_sec) break;
8636 switch (mysig) {
8637 case SIG_FXSLS: /* only interesting for FXS */
8638 case SIG_FXSGS:
8639 case SIG_FXSKS:
8640 case SIG_EM:
8641 case SIG_EM_E1:
8642 case SIG_EMWINK:
8643 case SIG_FEATD:
8644 case SIG_SF:
8645 case SIG_SFWINK:
8646 case SIG_SF_FEATD:
8647 if (!ast_strlen_zero(p->dop.dialstr)) {
8648 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8649 if (res) {
8650 p->dop.dialstr[0] = '\0';
8651 return NULL;
8652 } else
8653 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8654 }
8655 p->dop.dialstr[0] = '\0';
8656 p->dop.op = DAHDI_DIAL_OP_REPLACE;
8657 break;
8658 case SIG_FEATDMF:
8659 case SIG_FEATDMF_TA:
8660 case SIG_E911:
8661 case SIG_FGC_CAMA:
8662 case SIG_FGC_CAMAMF:
8663 case SIG_FEATB:
8664 case SIG_SF_FEATDMF:
8665 case SIG_SF_FEATB:
8666 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
8667 break;
8668 default:
8669 break;
8670 }
8671 break;
8672 case DAHDI_EVENT_POLARITY:
8673 /*
8674 * If we get a Polarity Switch event, check to see
8675 * if we should change the polarity state and
8676 * mark the channel as UP or if this is an indication
8677 * of remote end disconnect.
8678 */
8679 if (p->polarity == POLARITY_IDLE) {
8681 if (p->answeronpolarityswitch &&
8684 ast_debug(1, "Answering on polarity switch!\n");
8686 if (p->hanguponpolarityswitch) {
8688 }
8689 } else
8690 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8691 }
8692 /* Removed else statement from here as it was preventing hangups from ever happening*/
8693 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
8694 if (p->hanguponpolarityswitch &&
8695 (p->polarityonanswerdelay > 0) &&
8696 (p->polarity == POLARITY_REV) &&
8698 /* Added log_debug information below to provide a better indication of what is going on */
8699 ast_debug(1, "Polarity Reversal event occurred - 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) );
8700
8702 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
8705 } else
8706 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));
8707
8708 } else {
8710 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8711 }
8712 /* Added more log_debug information below to provide a better indication of what is going on */
8713 ast_debug(1, "Polarity Reversal event occurred - 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) );
8714 break;
8715 default:
8716 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
8717 }
8718 return &p->subs[idx].f;
8719}
#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:5332
static void dahdi_train_ec(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5023
static int attempt_transfer(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7578
static void * analog_ss_thread(void *data)
Definition: chan_dahdi.c:9982
static void handle_clear_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:3866
static int check_for_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7611
static int has_voicemail(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5363
#define CALLPROGRESS_PROGRESS
Definition: chan_dahdi.c:749
static void handle_alarms(struct dahdi_pvt *p, int alms)
Definition: chan_dahdi.c:7797
static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
Definition: chan_dahdi.c:7664
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:9623
#define MIN_MS_SINCE_FLASH
Definition: chan_dahdi.c:873
#define ast_channel_trylock(chan)
Definition: channel.h:2974
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1204
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition: channel.c:1229
void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value)
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1168
@ 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:2353
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:2331
#define DLA_LOCK(lock)
Definition: lock.h:499
#define DLA_UNLOCK(lock)
Definition: lock.h:497
#define CHANNEL_DEADLOCK_AVOIDANCE(chan)
Definition: lock.h:481
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:422
int ani2
Automatic Number Identification 2 (Info Digits)
Definition: channel.h:435
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:429
struct ast_party_name name
Subscriber name.
Definition: channel.h:342
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:281
char * str
Subscriber name (Malloced)
Definition: channel.h:266
unsigned int dahditrcallerid
TRUE if we should use the callerid from incoming call on dahdi transfer.
Definition: chan_dahdi.h:412
int polarityonanswerdelay
Minimal time period (ms) between the answer polarity switch and hangup polarity switch.
Definition: chan_dahdi.h:733
struct dahdi_pvt * oprpeer
Definition: chan_dahdi.h:152
char * origcid_name
Definition: chan_dahdi.h:545
int whichwink
Definition: chan_dahdi.h:703
char * origcid_num
Definition: chan_dahdi.h:544
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:372
int echotraining
Echo training time. 0 = disabled.
Definition: chan_dahdi.h:640
struct timeval polaritydelaytv
Start delay time if polarityonanswerdelay is nonzero.
Definition: chan_dahdi.h:735
unsigned int echobreak
XXX BOOLEAN Purpose???
Definition: chan_dahdi.h:264
char echorest[20]
Filled with 'w'. XXX Purpose??
Definition: chan_dahdi.h:642
char finaldial[64]
Second part of SIG_FEATDMF_TA wink operation.
Definition: chan_dahdi.h:705
unsigned int transfertobusy
TRUE if allowed to flash-transfer to busy channels.
Definition: chan_dahdi.h:417
unsigned int pulsedial
TRUE if a pulsed digit was detected. (Pulse dial phone detected)
Definition: chan_dahdi.h:360
char mohsuggest[MAX_MUSICCLASS]
Suggested music-on-hold class for peer channel to use for calls.
Definition: chan_dahdi.h:523
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 6320 of file chan_dahdi.c.

6321{
6322 int res = 0;
6323 int idx,x;
6324 int law;
6325 /*static int restore_gains(struct dahdi_pvt *p);*/
6326 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6327 struct dahdi_params par;
6328
6329 ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
6330 if (!ast_channel_tech_pvt(ast)) {
6331 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
6332 return 0;
6333 }
6334
6335 ast_mutex_lock(&p->lock);
6336 p->exten[0] = '\0';
6337 /* Always use sig_analog hangup handling for operator mode */
6338 if (dahdi_analog_lib_handles(p->sig, p->radio, 0)) {
6339 p->oprmode = 0;
6340 dahdi_confmute(p, 0);
6341 restore_gains(p);
6342 p->ignoredtmf = 0;
6343 p->waitingfordt.tv_sec = 0;
6344
6345 res = analog_hangup(p->sig_pvt, ast);
6346 revert_fax_buffers(p, ast);
6347
6348 goto hangup_out;
6349 } else {
6350 p->cid_num[0] = '\0';
6351 p->cid_name[0] = '\0';
6352 p->cid_subaddr[0] = '\0';
6353 }
6354
6355#if defined(HAVE_PRI)
6357 x = 1;
6358 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6359
6360 dahdi_confmute(p, 0);
6361 p->muting = 0;
6362 restore_gains(p);
6363 if (p->dsp) {
6364 ast_dsp_free(p->dsp);
6365 p->dsp = NULL;
6366 }
6367 p->ignoredtmf = 0;
6368
6369 /* Real channel, do some fixup */
6370 p->subs[SUB_REAL].owner = NULL;
6371 p->subs[SUB_REAL].needbusy = 0;
6373
6374 p->owner = NULL;
6375 p->cid_tag[0] = '\0';
6376 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */
6377 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
6378 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
6379 p->outgoing = 0;
6380 p->digital = 0;
6381 p->faxhandled = 0;
6382 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
6383
6384 revert_fax_buffers(p, ast);
6385
6386 p->law = p->law_default;
6387 law = p->law_default;
6388 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6389 if (res < 0) {
6390 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
6391 p->channel, strerror(errno));
6392 }
6393
6394 sig_pri_hangup(p->sig_pvt, ast);
6395
6396 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6398
6399 x = 0;
6400 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
6401 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
6402
6403 p->rdnis[0] = '\0';
6405 reset_conf(p);
6406
6407 /* Restore data mode */
6408 x = 0;
6409 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6410
6411 if (num_restart_pending == 0) {
6413 }
6414 goto hangup_out;
6415 }
6416#endif /* defined(HAVE_PRI) */
6417
6418#if defined(HAVE_SS7)
6419 if (p->sig == SIG_SS7) {
6420 x = 1;
6421 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6422
6423 dahdi_confmute(p, 0);
6424 p->muting = 0;
6425 restore_gains(p);
6426 if (p->dsp) {
6427 ast_dsp_free(p->dsp);
6428 p->dsp = NULL;
6429 }
6430 p->ignoredtmf = 0;
6431
6432 /* Real channel, do some fixup */
6433 p->subs[SUB_REAL].owner = NULL;
6434 p->subs[SUB_REAL].needbusy = 0;
6436
6437 p->owner = NULL;
6438 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */
6439 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
6440 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
6441 p->outgoing = 0;
6442 p->digital = 0;
6443 p->faxhandled = 0;
6444 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
6445
6446 revert_fax_buffers(p, ast);
6447
6448 p->law = p->law_default;
6449 law = p->law_default;
6450 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6451 if (res < 0) {
6452 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
6453 p->channel, strerror(errno));
6454 }
6455
6456 sig_ss7_hangup(p->sig_pvt, ast);
6457
6458 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6460
6461 x = 0;
6462 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
6463 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
6464
6466 reset_conf(p);
6467
6468 /* Restore data mode */
6469 x = 0;
6470 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6471
6472 if (num_restart_pending == 0) {
6474 }
6475 goto hangup_out;
6476 }
6477#endif /* defined(HAVE_SS7) */
6478
6479 idx = dahdi_get_index(ast, p, 1);
6480
6481 dahdi_confmute(p, 0);
6482 p->muting = 0;
6483 restore_gains(p);
6484 if (p->origcid_num) {
6485 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
6487 p->origcid_num = NULL;
6488 }
6489 if (p->origcid_name) {
6490 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
6492 p->origcid_name = NULL;
6493 }
6494 if (p->dsp)
6496
6497 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
6498 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
6499 p->ignoredtmf = 0;
6500
6501 if (idx > -1) {
6502 /* Real channel, do some fixup */
6503 p->subs[idx].owner = NULL;
6504 p->subs[idx].needanswer = 0;
6505 p->subs[idx].needflash = 0;
6506 p->subs[idx].needringing = 0;
6507 p->subs[idx].needbusy = 0;
6508 p->subs[idx].needcongestion = 0;
6509 p->subs[idx].linear = 0;
6511 dahdi_setlinear(p->subs[idx].dfd, 0);
6512 if (idx == SUB_REAL) {
6513 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
6514 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
6515 if (p->subs[SUB_CALLWAIT].inthreeway) {
6516 /* We had flipped over to answer a callwait and now it's gone */
6517 ast_debug(1, "We were flipped over to the callwait, moving back and not owning.\n");
6518 /* Move to the call-wait, but un-own us until they flip back. */
6521 p->owner = NULL;
6522 } else {
6523 /* The three way hung up, but we still have a call wait */
6524 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
6527 if (p->subs[SUB_REAL].inthreeway) {
6528 /* This was part of a three way call. Immediately make way for
6529 another call */
6530 ast_debug(1, "Call was complete, setting owner to former third call\n");
6531 p->owner = p->subs[SUB_REAL].owner;
6532 } else {
6533 /* This call hasn't been completed yet... Set owner to NULL */
6534 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
6535 p->owner = NULL;
6536 }
6537 p->subs[SUB_REAL].inthreeway = 0;
6538 }
6539 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
6540 /* Move to the call-wait and switch back to them. */
6543 p->owner = p->subs[SUB_REAL].owner;
6545 p->subs[SUB_REAL].needanswer = 1;
6547 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
6550 if (p->subs[SUB_REAL].inthreeway) {
6551 /* This was part of a three way call. Immediately make way for
6552 another call */
6553 ast_debug(1, "Call was complete, setting owner to former third call\n");
6554 p->owner = p->subs[SUB_REAL].owner;
6555 } else {
6556 /* This call hasn't been completed yet... Set owner to NULL */
6557 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
6558 p->owner = NULL;
6559 }
6560 p->subs[SUB_REAL].inthreeway = 0;
6561 }
6562 } else if (idx == SUB_CALLWAIT) {
6563 /* Ditch the holding callwait call, and immediately make it available */
6564 if (p->subs[SUB_CALLWAIT].inthreeway) {
6565 /* This is actually part of a three way, placed on hold. Place the third part
6566 on music on hold now */
6567 if (p->subs[SUB_THREEWAY].owner) {
6569 }
6571 /* Make it the call wait now */
6574 } else
6576 } else if (idx == SUB_THREEWAY) {
6577 if (p->subs[SUB_CALLWAIT].inthreeway) {
6578 /* The other party of the three way call is currently in a call-wait state.
6579 Start music on hold for them, and take the main guy out of the third call */
6580 if (p->subs[SUB_CALLWAIT].owner) {
6582 }
6584 }
6585 p->subs[SUB_REAL].inthreeway = 0;
6586 /* If this was part of a three way call index, let us make
6587 another three way call */
6589 } else {
6590 /* This wasn't any sort of call, but how are we an index? */
6591 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
6592 }
6593 }
6594
6595 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
6596 p->owner = NULL;
6597 p->ringt = 0;
6598 p->distinctivering = 0;
6599 p->confirmanswer = 0;
6600 p->outgoing = 0;
6601 p->digital = 0;
6602 p->faxhandled = 0;
6603 p->pulsedial = 0;
6604 if (p->dsp) {
6605 ast_dsp_free(p->dsp);
6606 p->dsp = NULL;
6607 }
6608
6609 revert_fax_buffers(p, ast);
6610
6611 p->law = p->law_default;
6612 law = p->law_default;
6613 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6614 if (res < 0)
6615 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
6616 /* Perform low level hangup if no owner left */
6617#ifdef HAVE_OPENR2
6618 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
6619 ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
6620 /* If it's an incoming call, check the mfcr2_forced_release setting */
6621 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
6622 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
6623 } else {
6624 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
6625 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
6626 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
6627 : dahdi_ast_cause_to_r2_cause(ast_channel_hangupcause(ast));
6628 dahdi_r2_disconnect_call(p, r2cause);
6629 }
6630 } else if (p->mfcr2call) {
6631 ast_debug(1, "Clearing call request on channel %d\n", p->channel);
6632 /* since ast_request() was called but not ast_call() we have not yet dialed
6633 and the openr2 stack will not call on_call_end callback, we need to unset
6634 the mfcr2call flag and bump the monitor count so the monitor thread can take
6635 care of this channel events from now on */
6636 p->mfcr2call = 0;
6637 }
6638#endif
6639 switch (p->sig) {
6640 case SIG_SS7:
6641 case SIG_MFCR2:
6643 case 0:
6644 break;
6645 default:
6646 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6647 break;
6648 }
6649 if (res < 0) {
6650 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
6651 }
6652 switch (p->sig) {
6653 case SIG_FXOGS:
6654 case SIG_FXOLS:
6655 case SIG_FXOKS:
6656 memset(&par, 0, sizeof(par));
6657 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
6658 if (!res) {
6659 struct analog_pvt *analog_p = p->sig_pvt;
6660#if 0
6661 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
6662#endif
6663 /* If they're off hook, try playing congestion */
6664 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
6665 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6666 else
6667 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6668 analog_p->fxsoffhookstate = par.rxisoffhook;
6669 }
6670 break;
6671 case SIG_FXSGS:
6672 case SIG_FXSLS:
6673 case SIG_FXSKS:
6674 /* Make sure we're not made available for at least two seconds assuming
6675 we were actually used for an inbound or outbound call. */
6677 time(&p->guardtime);
6678 p->guardtime += 2;
6679 }
6680 break;
6681 default:
6682 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6683 break;
6684 }
6685 if (p->sig)
6687 x = 0;
6688 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
6689 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
6690 p->didtdd = 0;
6691 p->callwaitcas = 0;
6694 p->waitingfordt.tv_sec = 0;
6695 p->dialing = 0;
6696 p->rdnis[0] = '\0';
6698 reset_conf(p);
6699 /* Restore data mode */
6700 switch (p->sig) {
6702 case SIG_SS7:
6703 x = 0;
6704 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
6705 break;
6706 default:
6707 break;
6708 }
6709 if (num_restart_pending == 0)
6711 }
6712
6713 p->callwaitingrepeat = 0;
6714 p->cidcwexpire = 0;
6715 p->cid_suppress_expire = 0;
6716 p->oprmode = 0;
6717hangup_out:
6719 ast_free(p->cidspill);
6720 p->cidspill = NULL;
6721
6722 if (p->reoriginate && p->sig == SIG_FXOKS && dahdi_analog_lib_handles(p->sig, p->radio, 0)) {
6723 /* Automatic reorigination: if all calls towards a user have hung up,
6724 * give dial tone again, so user doesn't need to cycle the hook state manually. */
6725 if (my_is_off_hook(p) && !p->owner) {
6726 /* 2 important criteria: channel must be off-hook, with no calls remaining (no owner) */
6727 ast_debug(1, "Queuing reorigination for channel %d\n", p->channel);
6728 my_play_tone(p, SUB_REAL, -1); /* Stop any congestion tone that may be present. */
6729 /* Must wait for the loop disconnect to end.
6730 * Sadly, these definitions are in dahdi/kernel.h, not dahdi/user.h
6731 * Calling usleep on an active DAHDI channel is a no-no, but this is okay.
6732 */
6733 usleep(800000); /* DAHDI_KEWLTIME + DAHDI_AFTERKEWLTIME */
6734 /* If the line is still off-hook and ownerless, actually queue the reorigination.
6735 * do_monitor will actually go ahead and do it. */
6736 if (!p->owner && my_is_off_hook(p)) {
6737 p->doreoriginate = 1; /* Tell do_monitor to reoriginate this channel */
6738 /* Note, my_off_hook will fail if called before the loop disconnect has finished
6739 * (important for FXOKS signaled channels). This is because DAHDI will reject
6740 * DAHDI_OFFHOOK while the channel is in TXSTATE_KEWL or TXSTATE_AFTERKEWL,
6741 * so we have to wait for that to finish (see comment above).
6742 * do_monitor itself cannot block, so make the blocking usleep call
6743 * here in the channel thread instead.
6744 */
6745 my_off_hook(p); /* Now, go ahead and take the channel back off hook (sig_analog put it on hook) */
6746 } else {
6747 ast_debug(1, "Channel %d is no longer eligible for reorigination (went back on hook or became in use)\n", p->channel);
6748 }
6749 }
6750 }
6751
6753 ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
6754
6756 if (p->restartpending) {
6758 }
6759
6760 if (p->destroy) {
6761 destroy_channel(p, 0);
6762 }
6764
6766 return 0;
6767}
static int reset_conf(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4899
static int num_restart_pending
Definition: chan_dahdi.c:836
static int my_is_off_hook(void *pvt)
Definition: chan_dahdi.c:2794
static int restart_monitor(void)
Definition: chan_dahdi.c:12266
static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
Definition: chan_dahdi.c:2666
static int my_off_hook(void *pvt)
Definition: chan_dahdi.c:2853
static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
Definition: chan_dahdi.c:6298
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:7395
#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:343
unsigned int restartpending
Definition: chan_dahdi.h:361
int distinctivering
Definition: chan_dahdi.h:725
time_t guardtime
Definition: chan_dahdi.h:593
char rdnis[AST_MAX_EXTENSION]
Redirecting Directory Number Information Service (RDNIS) number.
Definition: chan_dahdi.h:551
int law_default
Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
Definition: chan_dahdi.h:560
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:769
char cid_tag[AST_MAX_EXTENSION]
Caller ID tag from incoming call.
Definition: chan_dahdi.h:537
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 5670 of file chan_dahdi.c.

5671{
5672 /* Extract from the forward chain. */
5673 if (pvt->prev) {
5674 pvt->prev->next = pvt->next;
5675 } else if (iflist == pvt) {
5676 /* Node is at the head of the list. */
5677 iflist = pvt->next;
5678 }
5679
5680 /* Extract from the reverse chain. */
5681 if (pvt->next) {
5682 pvt->next->prev = pvt->prev;
5683 } else if (ifend == pvt) {
5684 /* Node is at the end of the list. */
5685 ifend = pvt->prev;
5686 }
5687
5688 /* Node is no longer in the list. */
5690 pvt->prev = NULL;
5691 pvt->next = NULL;
5692}
@ 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 5622 of file chan_dahdi.c.

5623{
5624 struct dahdi_pvt *cur;
5625
5627
5628 /* Find place in middle of list for the new interface. */
5629 for (cur = iflist; cur; cur = cur->next) {
5630 if (pvt->channel < cur->channel) {
5631 /* New interface goes before the current interface. */
5632 pvt->prev = cur->prev;
5633 pvt->next = cur;
5634 if (cur->prev) {
5635 /* Insert into the middle of the list. */
5636 cur->prev->next = pvt;
5637 } else {
5638 /* Insert at head of list. */
5639 iflist = pvt;
5640 }
5641 cur->prev = pvt;
5642 return;
5643 }
5644 }
5645
5646 /* New interface goes onto the end of the list */
5647 pvt->prev = ifend;
5648 pvt->next = NULL;
5649 if (ifend) {
5650 ifend->next = pvt;
5651 }
5652 ifend = pvt;
5653 if (!iflist) {
5654 /* List was empty */
5655 iflist = pvt;
5656 }
5657}
@ 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 9442 of file chan_dahdi.c.

9443{
9444 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9445 int res=-1;
9446 int idx;
9447 int func = DAHDI_FLASH;
9448
9449 ast_mutex_lock(&p->lock);
9450 ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
9451 switch (p->sig) {
9452#if defined(HAVE_PRI)
9454 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
9456 return res;
9457#endif /* defined(HAVE_PRI) */
9458#if defined(HAVE_SS7)
9459 case SIG_SS7:
9460 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
9462 return res;
9463#endif /* defined(HAVE_SS7) */
9464 default:
9465 break;
9466 }
9467#ifdef HAVE_OPENR2
9468 if (p->mfcr2 && !p->mfcr2_call_accepted) {
9470 /* if this is an R2 call and the call is not yet accepted, we don't want the
9471 tone indications to mess up with the MF tones */
9472 return 0;
9473 }
9474#endif
9475 idx = dahdi_get_index(chan, p, 0);
9476 if (idx == SUB_REAL) {
9477 switch (condition) {
9478 case AST_CONTROL_BUSY:
9479 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
9480 break;
9482 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
9483
9484 if (ast_channel_state(chan) != AST_STATE_UP) {
9485 if ((ast_channel_state(chan) != AST_STATE_RING) ||
9486 ((p->sig != SIG_FXSKS) &&
9487 (p->sig != SIG_FXSLS) &&
9488 (p->sig != SIG_FXSGS))) {
9489 /* We're playing audible ringback tone on the channel,
9490 * so set state to AST_STATE_RING, not AST_STATE_RINGING. */
9492 }
9493 }
9494 break;
9496 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
9497 /* act as a progress or proceeding, allowing the caller to enter additional numbers */
9498 res = 0;
9499 break;
9501 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
9502 /* don't continue in ast_indicate */
9503 res = 0;
9504 break;
9506 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
9507 /* don't continue in ast_indicate */
9508 res = 0;
9509 break;
9511 /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
9512 switch (ast_channel_hangupcause(chan)) {
9515 case 0:/* Cause has not been set. */
9516 /* Supply a more appropriate cause. */
9518 break;
9519 default:
9520 break;
9521 }
9522 break;
9523 case AST_CONTROL_HOLD:
9524 ast_moh_start(chan, data, p->mohinterpret);
9525 break;
9526 case AST_CONTROL_UNHOLD:
9527 ast_moh_stop(chan);
9528 break;
9530 if (p->radio)
9531 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
9532 res = 0;
9533 break;
9535 if (p->radio)
9536 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
9537 res = 0;
9538 break;
9539 case AST_CONTROL_FLASH:
9540 /* flash hookswitch */
9541 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
9542 /* Clear out the dial buffer */
9543 p->dop.dialstr[0] = '\0';
9544 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
9545 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
9546 ast_channel_name(chan), strerror(errno));
9547 } else
9548 res = 0;
9549 } else
9550 res = 0;
9551 break;
9553 res = 0;
9554 break;
9555 case -1:
9556 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9557 break;
9558 }
9559 } else {
9560 res = 0;
9561 }
9563 return res;
9564}
#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:7739
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7749
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:518

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

3795{
3796 for (;;) {
3797 if (!pvt->subs[sub_idx].owner) {
3798 /* No subchannel owner pointer */
3799 break;
3800 }
3801 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
3802 /* Got subchannel owner lock */
3803 break;
3804 }
3805 /* We must unlock the private to avoid the possibility of a deadlock */
3806 DEADLOCK_AVOIDANCE(&pvt->lock);
3807 }
3808}
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:486

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

7471{
7472 int x;
7473 if (!slave || !master) {
7474 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
7475 return;
7476 }
7477 for (x = 0; x < MAX_SLAVES; x++) {
7478 if (!master->slaves[x]) {
7479 master->slaves[x] = slave;
7480 break;
7481 }
7482 }
7483 if (x >= MAX_SLAVES) {
7484 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
7485 master->slaves[MAX_SLAVES - 1] = slave;
7486 }
7487 if (slave->master)
7488 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
7489 slave->master = master;
7490
7491 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
7492}

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

7415{
7416 /* Unlink a specific slave or all slaves/masters from a given master */
7417 int x;
7418 int hasslaves;
7419 if (!master)
7420 return;
7421 if (needlock) {
7422 ast_mutex_lock(&master->lock);
7423 if (slave) {
7424 while (ast_mutex_trylock(&slave->lock)) {
7425 DEADLOCK_AVOIDANCE(&master->lock);
7426 }
7427 }
7428 }
7429 hasslaves = 0;
7430 for (x = 0; x < MAX_SLAVES; x++) {
7431 if (master->slaves[x]) {
7432 if (!slave || (master->slaves[x] == slave)) {
7433 /* Take slave out of the conference */
7434 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
7435 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
7436 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
7437 master->slaves[x]->master = NULL;
7438 master->slaves[x] = NULL;
7439 } else
7440 hasslaves = 1;
7441 }
7442 if (!hasslaves)
7443 master->inconference = 0;
7444 }
7445 if (!slave) {
7446 if (master->master) {
7447 /* Take master out of the conference */
7448 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
7449 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
7450 hasslaves = 0;
7451 for (x = 0; x < MAX_SLAVES; x++) {
7452 if (master->master->slaves[x] == master)
7453 master->master->slaves[x] = NULL;
7454 else if (master->master->slaves[x])
7455 hasslaves = 1;
7456 }
7457 if (!hasslaves)
7458 master->master->inconference = 0;
7459 }
7460 master->master = NULL;
7461 }
7462 dahdi_conf_update(master);
7463 if (needlock) {
7464 if (slave)
7465 ast_mutex_unlock(&slave->lock);
7466 ast_mutex_unlock(&master->lock);
7467 }
7468}
#define ast_mutex_trylock(a)
Definition: lock.h:198

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

9624{
9625 struct ast_channel *tmp;
9626 struct ast_format_cap *caps;
9627 struct ast_format *deflaw;
9628 int x;
9629 int features;
9630 struct ast_str *chan_name;
9631 struct ast_variable *v;
9632 char *dashptr;
9633 char device_name[AST_CHANNEL_NAME];
9634
9635 if (i->subs[idx].owner) {
9636 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
9637 return NULL;
9638 }
9639
9640#if defined(HAVE_PRI)
9641 /*
9642 * The dnid has been stuffed with the called-number[:subaddress]
9643 * by dahdi_request() for outgoing calls.
9644 */
9645 chan_name = create_channel_name(i, i->outgoing, i->dnid);
9646#else
9647 chan_name = create_channel_name(i);
9648#endif /* defined(HAVE_PRI) */
9649 if (!chan_name) {
9650 return NULL;
9651 }
9652
9654 if (!caps) {
9655 ast_free(chan_name);
9656 return NULL;
9657 }
9658
9659 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));
9660 ast_free(chan_name);
9661 if (!tmp) {
9662 ao2_ref(caps, -1);
9663 return NULL;
9664 }
9665
9667
9668 if (callid) {
9669 ast_channel_callid_set(tmp, callid);
9670 }
9671
9673#if defined(HAVE_PRI)
9674 if (i->pri) {
9676 }
9677#endif /* defined(HAVE_PRI) */
9679 if (law) {
9680 i->law = law;
9681 if (law == DAHDI_LAW_ALAW) {
9682 deflaw = ast_format_alaw;
9683 } else {
9684 deflaw = ast_format_ulaw;
9685 }
9686 } else {
9687 switch (i->sig) {
9689 /* Make sure companding law is known. */
9690 i->law = (i->law_default == DAHDI_LAW_ALAW)
9691 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
9692 break;
9693 default:
9694 i->law = i->law_default;
9695 break;
9696 }
9697 if (i->law_default == DAHDI_LAW_ALAW) {
9698 deflaw = ast_format_alaw;
9699 } else {
9700 deflaw = ast_format_ulaw;
9701 }
9702 }
9703 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
9704 ast_format_cap_append(caps, deflaw, 0);
9706 ao2_ref(caps, -1);
9707 /* Start out assuming ulaw since it's smaller :) */
9708 ast_channel_set_rawreadformat(tmp, deflaw);
9709 ast_channel_set_readformat(tmp, deflaw);
9710 ast_channel_set_rawwriteformat(tmp, deflaw);
9711 ast_channel_set_writeformat(tmp, deflaw);
9712 i->subs[idx].linear = 0;
9713 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
9714 features = 0;
9715 if (idx == SUB_REAL) {
9716 if (i->busydetect && CANBUSYDETECT(i))
9717 features |= DSP_FEATURE_BUSY_DETECT;
9719 features |= DSP_FEATURE_CALL_PROGRESS;
9721 features |= DSP_FEATURE_WAITDIALTONE;
9722 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
9724 features |= DSP_FEATURE_FAX_DETECT;
9725 }
9726 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
9727 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
9728 i->hardwaredtmf = 0;
9729 features |= DSP_FEATURE_DIGIT_DETECT;
9730 } else if (NEED_MFDETECT(i)) {
9731 i->hardwaredtmf = 1;
9732 features |= DSP_FEATURE_DIGIT_DETECT;
9733 }
9734 }
9735 if (features) {
9736 if (i->dsp) {
9737 ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
9738 } else {
9739 if (i->channel != CHAN_PSEUDO)
9740 i->dsp = ast_dsp_new();
9741 else
9742 i->dsp = NULL;
9743 if (i->dsp) {
9744 i->dsp_features = features;
9745#if defined(HAVE_PRI) || defined(HAVE_SS7)
9746 /* We cannot do progress detection until receive PROGRESS message */
9747 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
9748 /* Remember requested DSP features, don't treat
9749 talking as ANSWER */
9750 i->dsp_features = features & ~DSP_PROGRESS_TALK;
9751 features = 0;
9752 }
9753#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9754 ast_dsp_set_features(i->dsp, features);
9758 if (i->busydetect && CANBUSYDETECT(i)) {
9761 }
9762 }
9763 }
9764 }
9765
9767
9768 if (state == AST_STATE_RING)
9769 ast_channel_rings_set(tmp, 1);
9771 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
9772 /* Only FXO signalled stuff can be picked up */
9777 }
9778 if (!ast_strlen_zero(i->parkinglot))
9779 ast_channel_parkinglot_set(tmp, i->parkinglot);
9780 if (!ast_strlen_zero(i->language))
9781 ast_channel_language_set(tmp, i->language);
9782 if (!i->owner)
9783 i->owner = tmp;
9785 ast_channel_accountcode_set(tmp, i->accountcode);
9786 if (i->amaflags)
9788 i->subs[idx].owner = tmp;
9790 if (!dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
9791 ast_channel_call_forward_set(tmp, i->call_forward);
9792 }
9793 /* If we've been told "no ADSI" then enforce it */
9794 if (!i->adsi)
9796 if (!ast_strlen_zero(i->exten))
9798 if (!ast_strlen_zero(i->rdnis)) {
9801 }
9802 if (!ast_strlen_zero(i->dnid)) {
9804 }
9805
9806 /* Don't use ast_set_callerid() here because it will
9807 * generate a needless NewCallerID event */
9808#if defined(HAVE_PRI) || defined(HAVE_SS7)
9809 if (!ast_strlen_zero(i->cid_ani)) {
9811 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_ani);
9812 } else if (!ast_strlen_zero(i->cid_num)) {
9815 }
9816#else
9817 if (!ast_strlen_zero(i->cid_num)) {
9820 }
9821#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9825 ast_channel_caller(tmp)->ani2 = i->cid_ani2;
9827 /* clear the fake event in case we posted one before we had ast_channel */
9828 i->fake_event = 0;
9829 /* Assure there is no confmute on this channel */
9830 dahdi_confmute(i, 0);
9831 i->muting = 0;
9832 /* Configure the new channel jb */
9834
9835 /* Set initial device state */
9836 ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
9837 dashptr = strrchr(device_name, '-');
9838 if (dashptr) {
9839 *dashptr = '\0';
9840 }
9843
9844 for (v = i->vars ; v ; v = v->next)
9846
9848
9849 ast_channel_unlock(tmp);
9850
9852
9854 if (startpbx) {
9855#ifdef HAVE_OPENR2
9856 if (i->mfcr2call) {
9857 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
9858 }
9859#endif
9860 if (ast_pbx_start(tmp)) {
9861 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
9862 ast_hangup(tmp);
9863 return NULL;
9864 }
9865 }
9866 return tmp;
9867}
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:860
#define CALLPROGRESS_FAX_INCOMING
Definition: chan_dahdi.c:751
#define CALLPROGRESS_FAX_OUTGOING
Definition: chan_dahdi.c:750
static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
Definition: chan_dahdi.c:2038
static struct ast_jb_conf global_jbconf
Definition: chan_dahdi.c:696
static char progzone[10]
Definition: chan_dahdi.c:796
#define CANBUSYDETECT(p)
Definition: chan_dahdi.c:784
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:1299
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:10456
@ AST_ADSI_UNAVAILABLE
Definition: channel.h:891
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)
@ AST_FLAG_DISABLE_DEVSTATE_CACHE
Definition: channel.h:1049
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:2395
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:474
#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:457
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4723
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::@210 number
Dialed/Called number.
char * str
Subscriber phone number (Malloced)
Definition: channel.h:388
char * tag
User-set "tag".
Definition: channel.h:356
int presentation
Q.931 encoded presentation-indicator encoded field.
Definition: channel.h:279
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:297
int plan
Q.931 Type-Of-Number and Numbering-Plan encoded fields.
Definition: channel.h:295
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:529
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:590
int busycount
Number of times to see "busy" tone before hanging up.
Definition: chan_dahdi.h:647
int waitfordialtone
Number of milliseconds to wait for dialtone.
Definition: chan_dahdi.h:662
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:676
char dnid[AST_MAX_EXTENSION]
Dialed Number Identifier.
Definition: chan_dahdi.h:553
struct ast_namedgroups * named_pickupgroups
Named pickup groups this belongs to.
Definition: chan_dahdi.h:585
int cid_ani2
Automatic Number Identification code from PRI.
Definition: chan_dahdi.h:530
struct ast_namedgroups * named_callgroups
Named call groups this belongs to.
Definition: chan_dahdi.h:580
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:575
int callingpres
Definition: chan_dahdi.h:598
char parkinglot[AST_MAX_EXTENSION]
Definition: chan_dahdi.h:524
int amaflags
Definition: chan_dahdi.h:707
char language[MAX_LANGUAGE]
Language configured for calls.
Definition: chan_dahdi.h:513
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_dahdi.h:706
struct ast_dsp_busy_pattern busy_cadence
Busy cadence pattern description.
Definition: chan_dahdi.h:652
ast_group_t callgroup
Bitmapped call groups this belongs to.
Definition: chan_dahdi.h:570
int dialtone_detect
Number of frames to watch for dialtone in incoming calls.
Definition: chan_dahdi.h:675
int cid_ton
Caller ID Q.931 TON/NPI field values. Set by PRI. Zero otherwise.
Definition: chan_dahdi.h:539

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

9615{
9616 struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, assignedids, requestor, callid);
9617
9619
9620 return new_channel;
9621}
ast_callid callid

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

4417{
4418 int fd;
4419 int isnum;
4420 int chan = 0;
4421 int bs;
4422 int x;
4423 isnum = 1;
4424 for (x = 0; x < strlen(fn); x++) {
4425 if (!isdigit(fn[x])) {
4426 isnum = 0;
4427 break;
4428 }
4429 }
4430 if (isnum) {
4431 chan = atoi(fn);
4432 if (chan < 1) {
4433 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
4434 return -1;
4435 }
4436 fn = "/dev/dahdi/channel";
4437 }
4438 fd = open(fn, O_RDWR | O_NONBLOCK);
4439 if (fd < 0) {
4440 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
4441 return -1;
4442 }
4443 if (chan) {
4444 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
4445 x = errno;
4446 close(fd);
4447 errno = x;
4448 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
4449 return -1;
4450 }
4451 }
4452 bs = READ_SIZE;
4453 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
4454 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
4455 x = errno;
4456 close(fd);
4457 errno = x;
4458 return -1;
4459 }
4460 return fd;
4461}
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 6864 of file chan_dahdi.c.

6865{
6866 char *cp;
6867 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
6868
6869 /* all supported options require data */
6870 if (!p || !data || (*datalen < 1)) {
6871 errno = EINVAL;
6872 return -1;
6873 }
6874
6875 switch (option) {
6876 case AST_OPTION_TDD:
6877 cp = (char *) data;
6878 if (p->mate) {
6879 *cp = 2;
6880 } else {
6881 *cp = p->tdd ? 1 : 0;
6882 }
6883 break;
6885 cp = (char *) data;
6886 *cp = p->ignoredtmf ? 0 : 1;
6887 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6888 break;
6890 cp = (char *) data;
6891 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
6892 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6893 break;
6895#if defined(HAVE_PRI)
6896#if defined(HAVE_PRI_CCSS)
6898 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
6899 break;
6900 }
6901#endif /* defined(HAVE_PRI_CCSS) */
6902#endif /* defined(HAVE_PRI) */
6903 return -1;
6904 default:
6905 return -1;
6906 }
6907
6908 errno = 0;
6909
6910 return 0;
6911}
#define AST_OPTION_DIGIT_DETECT
#define AST_OPTION_CC_AGENT_TYPE
#define AST_OPTION_FAX_DETECT
struct tdd_state * tdd
Definition: chan_dahdi.h:708
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 3819 of file chan_dahdi.c.

3820{
3821 for (;;) {
3822 if (p->owner) {
3823 if (ast_channel_trylock(p->owner)) {
3825 } else {
3826 ast_queue_frame(p->owner, f);
3828 break;
3829 }
3830 } else
3831 break;
3832 }
3833}
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:1169

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

8859{
8860 struct dahdi_pvt *p;
8861 int res;
8862 int idx;
8863 void *readbuf;
8864 struct ast_frame *f;
8865
8866 /*
8867 * For analog channels, we must do deadlock avoidance because
8868 * analog ports can have more than one Asterisk channel using
8869 * the same private structure.
8870 */
8871 p = ast_channel_tech_pvt(ast);
8872 while (ast_mutex_trylock(&p->lock)) {
8874
8875 /*
8876 * Check to see if the channel is still associated with the same
8877 * private structure. While the Asterisk channel was unlocked
8878 * the following events may have occurred:
8879 *
8880 * 1) A masquerade may have associated the channel with another
8881 * technology or private structure.
8882 *
8883 * 2) For PRI calls, call signaling could change the channel
8884 * association to another B channel (private structure).
8885 */
8886 if (ast_channel_tech_pvt(ast) != p) {
8887 /* The channel is no longer associated. Quit gracefully. */
8888 return &ast_null_frame;
8889 }
8890 }
8891
8892 idx = dahdi_get_index(ast, p, 0);
8893
8894 /* Hang up if we don't really exist */
8895 if (idx < 0) {
8896 ast_log(LOG_WARNING, "We don't exist?\n");
8898 return NULL;
8899 }
8900
8901 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
8903 return NULL;
8904 }
8905
8906 p->subs[idx].f.frametype = AST_FRAME_NULL;
8907 p->subs[idx].f.datalen = 0;
8908 p->subs[idx].f.samples = 0;
8909 p->subs[idx].f.mallocd = 0;
8910 p->subs[idx].f.offset = 0;
8911 p->subs[idx].f.subclass.integer = 0;
8912 p->subs[idx].f.delivery = ast_tv(0,0);
8913 p->subs[idx].f.src = "dahdi_read";
8914 p->subs[idx].f.data.ptr = NULL;
8915
8916 /* make sure it sends initial key state as first frame */
8917 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
8918 {
8919 struct dahdi_params ps;
8920
8921 memset(&ps, 0, sizeof(ps));
8922 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
8924 return NULL;
8925 }
8926 p->firstradio = 1;
8928 if (ps.rxisoffhook)
8929 {
8931 }
8932 else
8933 {
8935 }
8937 return &p->subs[idx].f;
8938 }
8939 if (p->ringt > 0) {
8940 if (!(--p->ringt)) {
8942 return NULL;
8943 }
8944 }
8945
8946#ifdef HAVE_OPENR2
8947 if (p->mfcr2) {
8948 openr2_chan_process_event(p->r2chan);
8949 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
8951 /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
8952 * now enqueue a progress frame to bridge the media up */
8953 if (p->mfcr2_call_accepted &&
8954 !p->mfcr2_progress_sent &&
8956 ast_debug(1, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
8957 ast_queue_frame(p->owner, &fr);
8958 p->mfcr2_progress_sent = 1;
8959 }
8960 }
8961 }
8962#endif
8963
8964 if (p->subs[idx].needringing) {
8965 /* Send ringing frame if requested */
8966 p->subs[idx].needringing = 0;
8971 return &p->subs[idx].f;
8972 }
8973
8974 if (p->subs[idx].needbusy) {
8975 /* Send busy frame if requested */
8976 p->subs[idx].needbusy = 0;
8980 return &p->subs[idx].f;
8981 }
8982
8983 if (p->subs[idx].needcongestion) {
8984 /* Send congestion frame if requested */
8985 p->subs[idx].needcongestion = 0;
8989 return &p->subs[idx].f;
8990 }
8991
8992 if (p->subs[idx].needanswer) {
8993 /* Send answer frame if requested */
8994 p->subs[idx].needanswer = 0;
8998 return &p->subs[idx].f;
8999 }
9000#ifdef HAVE_OPENR2
9001 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
9002 /* openr2 took care of reading and handling any event
9003 (needanswer, needbusy etc), if we continue we will read()
9004 twice, lets just return a null frame. This should only
9005 happen when openr2 is dialing out */
9007 return &ast_null_frame;
9008 }
9009#endif
9010
9011 if (p->subs[idx].needflash) {
9012 /* Send answer frame if requested */
9013 p->subs[idx].needflash = 0;
9017 return &p->subs[idx].f;
9018 }
9019
9020 if (p->subs[idx].needhold) {
9021 /* Send answer frame if requested */
9022 p->subs[idx].needhold = 0;
9026 ast_debug(1, "Sending hold on '%s'\n", ast_channel_name(ast));
9027 return &p->subs[idx].f;
9028 }
9029
9030 if (p->subs[idx].needunhold) {
9031 /* Send answer frame if requested */
9032 p->subs[idx].needunhold = 0;
9036 ast_debug(1, "Sending unhold on '%s'\n", ast_channel_name(ast));
9037 return &p->subs[idx].f;
9038 }
9039
9040 /*
9041 * If we have a fake_event, fake an exception to handle it only
9042 * if this channel owns the private.
9043 */
9044 if (p->fake_event && p->owner == ast) {
9045 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9046 struct analog_pvt *analog_p = p->sig_pvt;
9047
9048 f = analog_exception(analog_p, ast);
9049 } else {
9050 f = __dahdi_exception(ast);
9051 }
9053 return f;
9054 }
9055
9057 if (!p->subs[idx].linear) {
9058 p->subs[idx].linear = 1;
9059 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9060 if (res)
9061 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
9062 }
9063 } else {
9064 if (p->subs[idx].linear) {
9065 p->subs[idx].linear = 0;
9066 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9067 if (res)
9068 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
9069 }
9070 }
9071 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
9072 CHECK_BLOCKING(ast);
9073 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
9075 /* Check for hangup */
9076 if (res < 0) {
9077 f = NULL;
9078 if (res == -1) {
9079 if (errno == EAGAIN) {
9080 /* Return "NULL" frame if there is nobody there */
9082 return &p->subs[idx].f;
9083 } else if (errno == ELAST) {
9084 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9085 struct analog_pvt *analog_p = p->sig_pvt;
9086 f = analog_exception(analog_p, ast);
9087 } else {
9088 f = __dahdi_exception(ast);
9089 }
9090 } else
9091 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
9092 }
9094 return f;
9095 }
9096 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
9097 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
9098 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9099 struct analog_pvt *analog_p = p->sig_pvt;
9100 f = analog_exception(analog_p, ast);
9101 } else {
9102 f = __dahdi_exception(ast);
9103 }
9105 return f;
9106 }
9107 if (p->tdd) { /* if in TDD mode, see if we receive that */
9108 int c;
9109
9110 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
9111 if (c < 0) {
9112 ast_debug(1,"tdd_feed failed\n");
9114 return NULL;
9115 }
9116 if (c) { /* if a char to return */
9117 p->subs[idx].f.subclass.integer = 0;
9118 p->subs[idx].f.frametype = AST_FRAME_TEXT;
9119 p->subs[idx].f.mallocd = 0;
9120 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
9121 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
9122 p->subs[idx].f.datalen = 1;
9123 *((char *) p->subs[idx].f.data.ptr) = c;
9125 return &p->subs[idx].f;
9126 }
9127 }
9128 if (idx == SUB_REAL) {
9129 /* Ensure the CW timers decrement only on a single subchannel */
9130 if (p->cidcwexpire) {
9131 if (!--p->cidcwexpire) {
9132 /* Expired CID/CW */
9133 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
9135 }
9136 }
9137 if (p->cid_suppress_expire) {
9139 }
9140 if (p->callwaitingrepeat) {
9141 if (!--p->callwaitingrepeat) {
9142 /* Expired, Repeat callwaiting tone */
9143 ++p->callwaitrings;
9144 dahdi_callwait(ast);
9145 }
9146 }
9147 }
9148 if (p->subs[idx].linear) {
9149 p->subs[idx].f.datalen = READ_SIZE * 2;
9150 } else
9151 p->subs[idx].f.datalen = READ_SIZE;
9152
9153 /* Handle CallerID Transmission */
9154 if ((p->owner == ast) && p->cidspill) {
9155 send_callerid(p);
9156 }
9157
9158 p->subs[idx].f.frametype = AST_FRAME_VOICE;
9160 p->subs[idx].f.samples = READ_SIZE;
9161 p->subs[idx].f.mallocd = 0;
9162 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
9163 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
9164#if 0
9165 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
9166#endif
9167 if ((p->dialing && !p->waitingfordt.tv_sec) || p->radio || /* Transmitting something */
9168 (idx && (ast_channel_state(ast) != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
9169 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
9170 ) {
9171 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
9172 don't send anything */
9173 p->subs[idx].f.frametype = AST_FRAME_NULL;
9174 p->subs[idx].f.subclass.integer = 0;
9175 p->subs[idx].f.samples = 0;
9176 p->subs[idx].f.mallocd = 0;
9177 p->subs[idx].f.offset = 0;
9178 p->subs[idx].f.data.ptr = NULL;
9179 p->subs[idx].f.datalen= 0;
9180 }
9181 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec || p->dialtone_detect) && !idx) {
9182 /* Perform busy detection etc on the dahdi line */
9183 int mute;
9184
9186 && p->faxdetect_timeout
9188 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
9190 ast_debug(1, "Channel driver fax CNG detection timeout on %s\n",
9191 ast_channel_name(ast));
9192 }
9193
9194 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
9195
9196 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
9197 mute = ast_dsp_was_muted(p->dsp);
9198 if (p->muting != mute) {
9199 p->muting = mute;
9200 dahdi_confmute(p, mute);
9201 }
9202
9203 if (f) {
9205 && !p->outgoing && ast_channel_state(ast) == AST_STATE_UP) {
9207 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
9209 }
9210 }
9212 if ((ast_channel_state(ast) == AST_STATE_UP) && !p->outgoing) {
9213 /*
9214 * Treat this as a "hangup" instead of a "busy" on the
9215 * assumption that a busy means the incoming call went away.
9216 */
9217 ast_frfree(f);
9218 f = NULL;
9219 }
9220 } else if (p->dialtone_detect && !p->outgoing && f->frametype == AST_FRAME_VOICE) {
9222 /* Dialtone detected on inbound call; hangup the channel */
9223 ast_frfree(f);
9224 f = NULL;
9225 }
9226 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
9227 || f->frametype == AST_FRAME_DTMF_END) {
9228#ifdef HAVE_PRI
9230 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
9231 && p->pri
9232 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
9233 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
9234 /* Don't accept in-band DTMF when in overlap dial mode */
9235 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
9236 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
9237 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
9238
9240 f->subclass.integer = 0;
9241 }
9242#endif
9243 /* DSP clears us of being pulse */
9244 p->pulsedial = 0;
9245 } else if (p->waitingfordt.tv_sec) {
9247 p->waitingfordt.tv_sec = 0;
9248 ast_log(LOG_NOTICE, "Never saw dialtone on channel %d\n", p->channel);
9249 ast_frfree(f);
9250 f = NULL;
9251 } else if (f->frametype == AST_FRAME_VOICE) {
9253 f->subclass.integer = 0;
9255 p->waitingfordt.tv_sec = 0;
9256 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
9258 ast_debug(1, "Got 10 samples of dialtone!\n");
9259 if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
9260 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
9261 if (res) {
9262 p->dop.dialstr[0] = '\0';
9264 ast_frfree(f);
9265 return NULL;
9266 } else {
9267 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
9268 p->dialing = 1;
9269 p->dop.dialstr[0] = '\0';
9270 p->dop.op = DAHDI_DIAL_OP_REPLACE;
9272 }
9273 }
9274 }
9275 }
9276 }
9277 }
9278 } else
9279 f = &p->subs[idx].f;
9280
9281 if (f) {
9282 switch (f->frametype) {
9284 case AST_FRAME_DTMF_END:
9285 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9286 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
9287 } else {
9288 dahdi_handle_dtmf(ast, idx, &f);
9289 }
9291 if (f->frametype == AST_FRAME_DTMF_END) { /* only show this message when the key is let go of */
9292 ast_debug(1, "Dropping DTMF digit '%c' because tone dialing is disabled\n", f->subclass.integer);
9293 }
9295 f->subclass.integer = 0;
9296 }
9297 break;
9298 case AST_FRAME_VOICE:
9299 if (p->cidspill || p->cid_suppress_expire) {
9300 /* We are/were sending a caller id spill. Suppress any echo. */
9301 p->subs[idx].f.frametype = AST_FRAME_NULL;
9302 p->subs[idx].f.subclass.integer = 0;
9303 p->subs[idx].f.samples = 0;
9304 p->subs[idx].f.mallocd = 0;
9305 p->subs[idx].f.offset = 0;
9306 p->subs[idx].f.data.ptr = NULL;
9307 p->subs[idx].f.datalen= 0;
9308 }
9309 break;
9310 default:
9311 break;
9312 }
9313 }
9314
9316 return f;
9317}
static int dahdi_callwait(struct ast_channel *ast)
Definition: chan_dahdi.c:5429
struct ast_format * ast_channel_rawreadformat(struct ast_channel *chan)
#define CHECK_BLOCKING(c)
Set the blocking indication on the channel.
Definition: channel.h:2921
@ AST_FLAG_BLOCKING
Definition: channel.h:1005
int ast_channel_get_up_time(struct ast_channel *chan)
Obtain how long it has been since the channel was answered.
Definition: channel.c:2814
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:1748
#define DAHDI_OVERLAPDIAL_OUTGOING
Definition: sig_pri.h:252
struct ast_format * format
unsigned int faxdetect_timeout
The number of seconds into call to disable fax detection. (0 = disabled)
Definition: chan_dahdi.h:681
int waitfordialtoneduration
Transient variable. Stored off waitfordialtone duration at runtime.
Definition: chan_dahdi.h:670
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, 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 14005 of file chan_dahdi.c.

14008{
14009 int callwait = 0;
14010 struct dahdi_pvt *p;
14011 struct ast_channel *tmp = NULL;
14012 struct dahdi_pvt *exitpvt;
14013 int channelmatched = 0;
14014 int foundowner = 0;
14015 int groupmatched = 0;
14016#if defined(HAVE_PRI) || defined(HAVE_SS7)
14017 int transcapdigital = 0;
14018#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
14019 struct dahdi_starting_point start;
14020 ast_callid callid = 0;
14021 int callid_created = ast_callid_threadstorage_auto(&callid);
14022
14024 p = determine_starting_point(data, &start);
14025 if (!p) {
14026 /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
14028 ast_callid_threadstorage_auto_clean(callid, callid_created);
14029 return NULL;
14030 }
14031
14032 /* Search for an unowned channel */
14033 exitpvt = p;
14034 while (p && !tmp) {
14035 if (start.roundrobin)
14036 round_robin[start.rr_starting_point] = p;
14037
14038 if (p->owner) {
14039 foundowner++;
14040 }
14041
14042 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
14043 && available(&p, channelmatched)) {
14044 ast_debug(1, "Using channel %d\n", p->channel);
14045
14046 callwait = (p->owner != NULL);
14047#ifdef HAVE_OPENR2
14048 if (p->mfcr2) {
14049 ast_mutex_lock(&p->lock);
14050 if (p->mfcr2call) {
14052 ast_debug(1, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
14053 goto next;
14054 }
14055 p->mfcr2call = 1;
14057 }
14058#endif
14059 if (p->channel == CHAN_PSEUDO) {
14060 p = duplicate_pseudo(p);
14061 if (!p) {
14062 break;
14063 }
14064 }
14065
14066 p->distinctivering = 0;
14067 /* Make special notes */
14068 switch (start.opt) {
14069 case '\0':
14070 /* No option present. */
14071 break;
14072 case 'c':
14073 /* Confirm answer */
14074 p->confirmanswer = 1;
14075 break;
14076 case 'r':
14077 /* Distinctive ring */
14078 p->distinctivering = start.cadence;
14079 break;
14080 case 'd':
14081#if defined(HAVE_PRI) || defined(HAVE_SS7)
14082 /* If this is an ISDN call, make it digital */
14083 transcapdigital = AST_TRANS_CAP_DIGITAL;
14084#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
14085 break;
14086 default:
14087 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, data);
14088 break;
14089 }
14090
14091 p->outgoing = 1;
14092 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
14093 tmp = analog_request(p->sig_pvt, &callwait, requestor);
14094#ifdef HAVE_PRI
14095 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
14096 /*
14097 * We already have the B channel reserved for this call. We
14098 * just need to make sure that dahdi_hangup() has completed
14099 * cleaning up before continuing.
14100 */
14101 ast_mutex_lock(&p->lock);
14103
14105 sizeof(p->dnid));
14106 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, assignedids, requestor, transcapdigital);
14107#endif
14108#if defined(HAVE_SS7)
14109 } else if (p->sig == SIG_SS7) {
14110 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, assignedids, requestor, transcapdigital);
14111#endif /* defined(HAVE_SS7) */
14112 } else {
14113 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, assignedids, requestor, callid);
14114 }
14115 if (!tmp) {
14116 p->outgoing = 0;
14117#if defined(HAVE_PRI)
14118 switch (p->sig) {
14120#if defined(HAVE_PRI_CALL_WAITING)
14121 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
14122 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
14123 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
14124 }
14125#endif /* defined(HAVE_PRI_CALL_WAITING) */
14126 /*
14127 * This should be the last thing to clear when we are done with
14128 * the channel.
14129 */
14130 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
14131 break;
14132 default:
14133 break;
14134 }
14135#endif /* defined(HAVE_PRI) */
14136 } else {
14137 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", data);
14138 }
14139 break;
14140 }
14141#ifdef HAVE_OPENR2
14142next:
14143#endif
14144 if (start.backwards) {
14145 p = p->prev;
14146 if (!p)
14147 p = ifend;
14148 } else {
14149 p = p->next;
14150 if (!p)
14151 p = iflist;
14152 }
14153 /* stop when you roll to the one that we started from */
14154 if (p == exitpvt)
14155 break;
14156 }
14159 if (cause && !tmp) {
14160 if (callwait || (channelmatched && foundowner)) {
14161 *cause = AST_CAUSE_BUSY;
14162 } else if (groupmatched) {
14163 *cause = AST_CAUSE_CONGESTION;
14164 } else {
14165 /*
14166 * We did not match any channel requested.
14167 * Dialplan error requesting non-existant channel?
14168 */
14169 }
14170 }
14171
14172 ast_callid_threadstorage_auto_clean(callid, callid_created);
14173 return tmp;
14174}
#define AST_CAUSE_BUSY
Definition: causes.h:149
static struct dahdi_pvt * round_robin[64]
Definition: chan_dahdi.c:3760
static int available(struct dahdi_pvt **pvt, int is_specific_channel)
Definition: chan_dahdi.c:13574
static struct dahdi_pvt * duplicate_pseudo(struct dahdi_pvt *src)
Definition: chan_dahdi.c:13780
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:764
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:778
#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, and SUB_REAL.

◆ dahdi_restart()

static int dahdi_restart ( void  )
static

Definition at line 15943 of file chan_dahdi.c.

15944{
15945#if defined(HAVE_PRI) || defined(HAVE_SS7)
15946 int i, j;
15947#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15948 int cancel_code;
15949 struct dahdi_pvt *p;
15950
15952 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15954 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15955#ifdef HAVE_OPENR2
15956 dahdi_r2_destroy_links();
15957#endif
15958
15959#if defined(HAVE_PRI)
15960 for (i = 0; i < NUM_SPANS; i++) {
15961 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15962 cancel_code = pthread_cancel(pris[i].pri.master);
15963 pthread_kill(pris[i].pri.master, SIGURG);
15964 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);
15965 pthread_join(pris[i].pri.master, NULL);
15966 ast_debug(4, "Joined thread of span %d\n", i);
15967 }
15968 }
15969#endif
15970
15971#if defined(HAVE_SS7)
15972 for (i = 0; i < NUM_SPANS; i++) {
15973 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15974 cancel_code = pthread_cancel(linksets[i].ss7.master);
15975 pthread_kill(linksets[i].ss7.master, SIGURG);
15976 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);
15977 pthread_join(linksets[i].ss7.master, NULL);
15978 ast_debug(4, "Joined thread of span %d\n", i);
15979 }
15980 }
15981#endif /* defined(HAVE_SS7) */
15982
15985 cancel_code = pthread_cancel(monitor_thread);
15986 pthread_kill(monitor_thread, SIGURG);
15987 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15988 pthread_join(monitor_thread, NULL);
15989 ast_debug(4, "Joined monitor thread\n");
15990 }
15991 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15992
15994 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15995 int x = DAHDI_FLASH;
15996 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15997
15999 for (p = iflist; p; p = p->next) {
16000 if (p->owner) {
16001 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
16002 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
16003 }
16004 }
16007 }
16008
16009 /* ensure any created channels before monitor threads were stopped are hungup */
16011 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
16013 memset(round_robin, 0, sizeof(round_robin));
16014 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
16015
16017
16018#ifdef HAVE_PRI
16019 for (i = 0; i < NUM_SPANS; i++) {
16020 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
16021 dahdi_close_pri_fd(&(pris[i]), j);
16022 }
16023
16024 memset(pris, 0, sizeof(pris));
16025 for (i = 0; i < NUM_SPANS; i++) {
16026 sig_pri_init_pri(&pris[i].pri);
16027 }
16028 pri_set_error(dahdi_pri_error);
16029 pri_set_message(dahdi_pri_message);
16030#endif
16031#if defined(HAVE_SS7)
16032 for (i = 0; i < NUM_SPANS; i++) {
16033 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
16034 dahdi_close_ss7_fd(&(linksets[i]), j);
16035 }
16036
16037 memset(linksets, 0, sizeof(linksets));
16038 for (i = 0; i < NUM_SPANS; i++) {
16039 sig_ss7_init_linkset(&linksets[i].ss7);
16040 }
16041 ss7_set_error(dahdi_ss7_error);
16042 ss7_set_message(dahdi_ss7_message);
16043 ss7_set_hangup(sig_ss7_cb_hangup);
16044 ss7_set_notinservice(sig_ss7_cb_notinservice);
16045 ss7_set_call_null(sig_ss7_cb_call_null);
16046#endif /* defined(HAVE_SS7) */
16047
16048 if (setup_dahdi(2) != 0) {
16049 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
16051 return 1;
16052 }
16055 return 0;
16056}
static void dahdi_softhangup_all(void)
Definition: chan_dahdi.c:15915
static int setup_dahdi(int reload)
Definition: chan_dahdi.c:20356
static ast_mutex_t restart_lock
Definition: chan_dahdi.c:834
int ast_active_channels(void)
returns number of active/allocated channels
Definition: channel.c:498
#define ast_cond_wait(cond, mutex)
Definition: lock.h:212
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 16058 of file chan_dahdi.c.

16059{
16060 switch (cmd) {
16061 case CLI_INIT:
16062 e->command = "dahdi restart";
16063 e->usage =
16064 "Usage: dahdi restart\n"
16065 " Restarts the DAHDI channels: destroys them all and then\n"
16066 " re-reads them from chan_dahdi.conf.\n"
16067 " Note that this will STOP any running CALL on DAHDI channels.\n"
16068 "";
16069 return NULL;
16070 case CLI_GENERATE:
16071 return NULL;
16072 }
16073 if (a->argc != 2)
16074 return CLI_SHOWUSAGE;
16075
16076 if (dahdi_restart() != 0)
16077 return CLI_FAILURE;
16078 return CLI_SUCCESS;
16079}

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

7535{
7536 int x;
7537 int res;
7538 /* Make sure our transmit state is on hook */
7539 x = 0;
7540 x = DAHDI_ONHOOK;
7541 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7542 do {
7543 x = DAHDI_RING;
7544 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7545 if (res) {
7546 switch (errno) {
7547 case EBUSY:
7548 case EINTR:
7549 /* Wait just in case */
7550 usleep(10000);
7551 continue;
7552 case EINPROGRESS:
7553 res = 0;
7554 break;
7555 default:
7556 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
7557 res = 0;
7558 }
7559 }
7560 } while (res);
7561 return res;
7562}

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

20495{
20496#define END_SILENCE_LEN 400
20497#define HEADER_MS 50
20498#define TRAILER_MS 5
20499#define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
20500#define ASCII_BYTES_PER_CHAR 80
20501
20502 unsigned char *buf,*mybuf;
20503 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
20504 struct pollfd fds[1];
20505 int size,res,fd,len,x;
20506 int bytes=0;
20507 int idx;
20508
20509 /*
20510 * Initial carrier (imaginary)
20511 *
20512 * Note: The following float variables are used by the
20513 * PUT_CLID_MARKMS and PUT_CLID() macros.
20514 */
20515 float cr = 1.0;
20516 float ci = 0.0;
20517 float scont = 0.0;
20518
20519 if (!text[0]) {
20520 return(0); /* if nothing to send, don't */
20521 }
20522 idx = dahdi_get_index(c, p, 0);
20523 if (idx < 0) {
20524 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
20525 return -1;
20526 }
20527 if ((!p->tdd) && (!p->mate)) {
20528#if defined(HAVE_PRI)
20529#if defined(HAVE_PRI_DISPLAY_TEXT)
20530 ast_mutex_lock(&p->lock);
20532 sig_pri_sendtext(p->sig_pvt, text);
20533 }
20535#endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
20536#endif /* defined(HAVE_PRI) */
20537 return(0); /* if not in TDD mode, just return */
20538 }
20539 if (p->mate)
20541 else
20542 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
20543 if (!buf)
20544 return -1;
20545 mybuf = buf;
20546 if (p->mate) {
20547 /* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
20548 struct ast_format *codec = AST_LAW(p);
20549
20550 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
20552 }
20553 /* Put actual message */
20554 for (x = 0; text[x]; x++) {
20555 PUT_CLID(text[x]);
20556 }
20557 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
20559 }
20560 len = bytes;
20561 buf = mybuf;
20562 } else {
20563 len = tdd_generate(p->tdd, buf, text);
20564 if (len < 1) {
20565 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
20566 ast_free(mybuf);
20567 return -1;
20568 }
20569 }
20570 memset(buf + len, 0x7f, END_SILENCE_LEN);
20572 fd = p->subs[idx].dfd;
20573 while (len) {
20574 if (ast_check_hangup(c)) {
20575 ast_free(mybuf);
20576 return -1;
20577 }
20578 size = len;
20579 if (size > READ_SIZE)
20580 size = READ_SIZE;
20581 fds[0].fd = fd;
20582 fds[0].events = POLLOUT | POLLPRI;
20583 fds[0].revents = 0;
20584 res = poll(fds, 1, -1);
20585 if (!res) {
20586 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
20587 continue;
20588 }
20589 /* if got exception */
20590 if (fds[0].revents & POLLPRI) {
20591 ast_free(mybuf);
20592 return -1;
20593 }
20594 if (!(fds[0].revents & POLLOUT)) {
20595 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
20596 continue;
20597 }
20598 res = write(fd, buf, size);
20599 if (res != size) {
20600 if (res == -1) {
20601 ast_free(mybuf);
20602 return -1;
20603 }
20604 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
20605 break;
20606 }
20607 len -= size;
20608 buf += size;
20609 }
20610 ast_free(mybuf);
20611 return(0);
20612}
char * text
Definition: app_queue.c:1809
#define PUT_CLID(byte)
Definition: callerid.h:412
#define PUT_CLID_MARKMS
Definition: callerid.h:397
#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:444
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 16697 of file chan_dahdi.c.

16698{
16699 int channel;
16700 int on;
16701 struct dahdi_pvt *dahdi_chan = NULL;
16702
16703 switch (cmd) {
16704 case CLI_INIT:
16705 e->command = "dahdi set dnd";
16706 e->usage =
16707 "Usage: dahdi set dnd <chan#> <on|off>\n"
16708 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16709 " Changes take effect immediately.\n"
16710 " <chan num> is the channel number\n"
16711 " <on|off> Enable or disable DND mode?\n"
16712 ;
16713 return NULL;
16714 case CLI_GENERATE:
16715 return NULL;
16716 }
16717
16718 if (a->argc != 5)
16719 return CLI_SHOWUSAGE;
16720
16721 if ((channel = atoi(a->argv[3])) <= 0) {
16722 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16723 return CLI_SHOWUSAGE;
16724 }
16725
16726 if (ast_true(a->argv[4]))
16727 on = 1;
16728 else if (ast_false(a->argv[4]))
16729 on = 0;
16730 else {
16731 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16732 return CLI_SHOWUSAGE;
16733 }
16734
16736 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16737 if (dahdi_chan->channel != channel)
16738 continue;
16739
16740 /* Found the channel. Actually set it */
16741 dahdi_dnd(dahdi_chan, on);
16742 break;
16743 }
16745
16746 if (!dahdi_chan) {
16747 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16748 return CLI_FAILURE;
16749 }
16750
16751 return CLI_SUCCESS;
16752}
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 5252 of file chan_dahdi.c.

5253{
5254 int x, res;
5255
5256 x = hs;
5257 res = ioctl(fd, DAHDI_HOOK, &x);
5258
5259 if (res < 0) {
5260 if (errno == EINPROGRESS)
5261 return 0;
5262 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
5263 /* will expectedly fail if phone is off hook during operation, such as during a restart */
5264 }
5265
5266 return res;
5267}

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

16541{
16542 int channel;
16543 float gain;
16544 int tx;
16545 struct dahdi_pvt *tmp = NULL;
16546
16547 switch (cmd) {
16548 case CLI_INIT:
16549 e->command = "dahdi set hwgain {rx|tx}";
16550 e->usage =
16551 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
16552 " Sets the hardware gain on a given channel and overrides the\n"
16553 " value provided at module loadtime. Changes take effect\n"
16554 " immediately whether the channel is in use or not.\n"
16555 "\n"
16556 " <rx|tx> which direction do you want to change (relative to our module)\n"
16557 " <chan num> is the channel number relative to the device\n"
16558 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
16559 "\n"
16560 " Please note:\n"
16561 " * hwgain is only supportable by hardware with analog ports because\n"
16562 " hwgain works on the analog side of an analog-digital conversion.\n";
16563 return NULL;
16564 case CLI_GENERATE:
16565 return NULL;
16566 }
16567
16568 if (a->argc != 6)
16569 return CLI_SHOWUSAGE;
16570
16571 if (!strcasecmp("rx", a->argv[3]))
16572 tx = 0; /* rx */
16573 else if (!strcasecmp("tx", a->argv[3]))
16574 tx = 1; /* tx */
16575 else
16576 return CLI_SHOWUSAGE;
16577
16578 channel = atoi(a->argv[4]);
16579 gain = atof(a->argv[5]);
16580
16582
16583 for (tmp = iflist; tmp; tmp = tmp->next) {
16584
16585 if (tmp->channel != channel)
16586 continue;
16587
16588 if (tmp->subs[SUB_REAL].dfd == -1)
16589 break;
16590
16591 if (set_hwgain(tmp->subs[SUB_REAL].dfd, gain, tx)) {
16592 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
16594 return CLI_FAILURE;
16595 }
16596 ast_cli(a->fd, "Hardware %s gain set to %.1f dB on channel %d.\n",
16597 tx ? "tx" : "rx", gain, channel);
16598
16599 if (tx) {
16600 tmp->hwtxgain_enabled = 1;
16601 tmp->hwtxgain = gain;
16602 } else {
16603 tmp->hwrxgain_enabled = 1;
16604 tmp->hwrxgain = gain;
16605 }
16606 break;
16607 }
16608
16610
16611 if (tmp)
16612 return CLI_SUCCESS;
16613
16614 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16615 return CLI_FAILURE;
16616
16617}
static int set_hwgain(int fd, float gain, int tx_direction)
Definition: chan_dahdi.c:5058
unsigned int hwtxgain_enabled
TRUE if hardware Tx gain set by Asterisk.
Definition: chan_dahdi.h:475
float hwrxgain
Hardware Rx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:154
float hwtxgain
Hardware Tx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:156
unsigned int hwrxgain_enabled
TRUE if hardware Rx gain set by Asterisk.
Definition: chan_dahdi.h:473

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, dahdi_subchannel::dfd, errno, dahdi_pvt::hwrxgain, dahdi_pvt::hwrxgain_enabled, dahdi_pvt::hwtxgain, dahdi_pvt::hwtxgain_enabled, iflist, iflock, dahdi_pvt::next, NULL, set_hwgain(), SUB_REAL, dahdi_pvt::subs, 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 16754 of file chan_dahdi.c.

16755{
16756 int channel;
16757 int on;
16758 int override = 1;
16759 struct dahdi_pvt *dahdi_chan = NULL;
16760
16761 switch (cmd) {
16762 case CLI_INIT:
16763 e->command = "dahdi set mwi";
16764 e->usage =
16765 "Usage: dahdi set mwi <chan#> <on|off|reset>\n"
16766 " Sets/unsets MWI (Message Waiting Indicator) manually on a channel.\n"
16767 " This may be used regardless of whether the channel is assigned any mailboxes.\n"
16768 " When active, this setting will override the voicemail status to set MWI.\n"
16769 " Once cleared, the voicemail status will resume control of MWI.\n"
16770 " Changes are queued for when the channel is idle and persist until cleared.\n"
16771 " <chan num> is the channel number\n"
16772 " <on|off|reset> Enable, disable, or reset Message Waiting Indicator override?\n"
16773 ;
16774 return NULL;
16775 case CLI_GENERATE:
16776 return NULL;
16777 }
16778
16779 if (a->argc != 5)
16780 return CLI_SHOWUSAGE;
16781
16782 if ((channel = atoi(a->argv[3])) <= 0) {
16783 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16784 return CLI_SHOWUSAGE;
16785 }
16786
16787 if (ast_true(a->argv[4])) {
16788 on = 1;
16789 } else if (ast_false(a->argv[4])) {
16790 on = 0;
16791 } else if (!strcmp(a->argv[4], "reset")) {
16792 override = 0;
16793 } else {
16794 ast_cli(a->fd, "Expected 'on' or 'off' or 'reset', got '%s'\n", a->argv[4]);
16795 return CLI_SHOWUSAGE;
16796 }
16797
16799 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16800 if (dahdi_chan->channel != channel)
16801 continue;
16802
16803 /* Found the channel. Actually set it */
16804 if (override) {
16805 dahdi_chan->mwioverride_disposition = on;
16806 ast_cli(a->fd, "MWI '%s' queued for channel %d\n", on ? "enable" : "disable", channel);
16807 }
16808 dahdi_chan->mwioverride_active = override;
16809 /* The do_monitor thread will take care of actually sending the MWI
16810 * at an appropriate time for the channel. */
16811 break;
16812 }
16814
16815 if (!dahdi_chan) {
16816 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16817 return CLI_FAILURE;
16818 }
16819
16820 return CLI_SUCCESS;
16821}
unsigned int mwioverride_active
TRUE if a manual MWI override is active for a channel.
Definition: chan_dahdi.h:439
unsigned int mwioverride_disposition
Manual MWI disposition (on/off)
Definition: chan_dahdi.h:441

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

16620{
16621 int channel;
16622 float gain;
16623 int tx;
16624 int res;
16625 struct dahdi_pvt *tmp = NULL;
16626
16627 switch (cmd) {
16628 case CLI_INIT:
16629 e->command = "dahdi set swgain {rx|tx}";
16630 e->usage =
16631 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
16632 " Sets the software gain on a given channel and overrides the\n"
16633 " value provided at module loadtime. Changes take effect\n"
16634 " immediately whether the channel is in use or not.\n"
16635 "\n"
16636 " <rx|tx> which direction do you want to change (relative to our module)\n"
16637 " <chan num> is the channel number relative to the device\n"
16638 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16639 return NULL;
16640 case CLI_GENERATE:
16641 return NULL;
16642 }
16643
16644 if (a->argc != 6)
16645 return CLI_SHOWUSAGE;
16646
16647 if (!strcasecmp("rx", a->argv[3]))
16648 tx = 0; /* rx */
16649 else if (!strcasecmp("tx", a->argv[3]))
16650 tx = 1; /* tx */
16651 else
16652 return CLI_SHOWUSAGE;
16653
16654 channel = atoi(a->argv[4]);
16655 gain = atof(a->argv[5]);
16656
16658 for (tmp = iflist; tmp; tmp = tmp->next) {
16659
16660 if (tmp->channel != channel)
16661 continue;
16662
16663 if (tmp->subs[SUB_REAL].dfd == -1)
16664 break;
16665
16666 if (tx)
16667 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
16668 else
16669 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
16670
16671 if (res) {
16672 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
16674 return CLI_FAILURE;
16675 }
16676
16677 ast_cli(a->fd, "Software %s gain set to %.2f dB on channel %d.\n",
16678 tx ? "tx" : "rx", gain, channel);
16679
16680 if (tx) {
16681 tmp->txgain = gain;
16682 } else {
16683 tmp->rxgain = gain;
16684 }
16685 break;
16686 }
16688
16689 if (tmp)
16690 return CLI_SUCCESS;
16691
16692 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16693 return CLI_FAILURE;
16694
16695}
static int set_actual_txgain(int fd, float gain, float drc, int law)
Definition: chan_dahdi.c:5186
static int set_actual_rxgain(int fd, float gain, float drc, int law)
Definition: chan_dahdi.c:5203

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, dahdi_subchannel::dfd, iflist, iflock, dahdi_pvt::law, dahdi_pvt::next, NULL, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::txdrc, dahdi_pvt::txgain, and ast_cli_entry::usage.

◆ dahdi_setlinear()

static int dahdi_setlinear ( int  dfd,
int  linear 
)
static

Definition at line 4491 of file chan_dahdi.c.

4492{
4493 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
4494}

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

6914{
6915 char *cp;
6916 signed char *scp;
6917 int x;
6918 int idx;
6919 struct dahdi_pvt *p = ast_channel_tech_pvt(chan), *pp;
6920 struct oprmode *oprmode;
6921
6922
6923 /* all supported options require data */
6924 if (!p || !data || (datalen < 1)) {
6925 errno = EINVAL;
6926 return -1;
6927 }
6928
6929 switch (option) {
6930 case AST_OPTION_TXGAIN:
6931 scp = (signed char *) data;
6932 idx = dahdi_get_index(chan, p, 0);
6933 if (idx < 0) {
6934 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
6935 return -1;
6936 }
6937 ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
6938 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
6939 case AST_OPTION_RXGAIN:
6940 scp = (signed char *) data;
6941 idx = dahdi_get_index(chan, p, 0);
6942 if (idx < 0) {
6943 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
6944 return -1;
6945 }
6946 ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
6947 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
6949 if (!p->dsp)
6950 break;
6951 cp = (char *) data;
6952 switch (*cp) {
6953 case 1:
6954 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
6955 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
6956 break;
6957 case 2:
6958 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
6959 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
6960 break;
6961 default:
6962 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
6963 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
6964 break;
6965 }
6966 break;
6967 case AST_OPTION_TDD:
6968 /* turn on or off TDD */
6969 cp = (char *) data;
6970 p->mate = 0;
6971 if (!*cp) { /* turn it off */
6972 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
6973 if (p->tdd)
6974 tdd_free(p->tdd);
6975 p->tdd = 0;
6976 break;
6977 }
6978 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
6979 (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
6981 /* otherwise, turn it on */
6982 if (!p->didtdd) { /* if haven't done it yet */
6983 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
6984 unsigned char *buf;
6985 int size, res, fd, len;
6986 struct pollfd fds[1];
6987
6988 buf = mybuf;
6989 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
6990 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
6991 len = 40000;
6992 idx = dahdi_get_index(chan, p, 0);
6993 if (idx < 0) {
6994 ast_log(LOG_WARNING, "No index in TDD?\n");
6995 return -1;
6996 }
6997 fd = p->subs[idx].dfd;
6998 while (len) {
6999 if (ast_check_hangup(chan))
7000 return -1;
7001 size = len;
7002 if (size > READ_SIZE)
7003 size = READ_SIZE;
7004 fds[0].fd = fd;
7005 fds[0].events = POLLPRI | POLLOUT;
7006 fds[0].revents = 0;
7007 res = poll(fds, 1, -1);
7008 if (!res) {
7009 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
7010 continue;
7011 }
7012 /* if got exception */
7013 if (fds[0].revents & POLLPRI)
7014 return -1;
7015 if (!(fds[0].revents & POLLOUT)) {
7016 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
7017 continue;
7018 }
7019 res = write(fd, buf, size);
7020 if (res != size) {
7021 if (res == -1) return -1;
7022 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
7023 break;
7024 }
7025 len -= size;
7026 buf += size;
7027 }
7028 p->didtdd = 1; /* set to have done it now */
7029 }
7030 if (*cp == 2) { /* Mate mode */
7031 if (p->tdd)
7032 tdd_free(p->tdd);
7033 p->tdd = 0;
7034 p->mate = 1;
7035 break;
7036 }
7037 if (!p->tdd) { /* if we don't have one yet */
7038 p->tdd = tdd_new(); /* allocate one */
7039 }
7040 break;
7041 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
7042 if (!p->dsp)
7043 break;
7044 cp = (char *) data;
7045 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
7046 *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
7048 break;
7049 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
7050#if defined(HAVE_PRI)
7052 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
7053 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
7054 break;
7055 }
7056#endif /* defined(HAVE_PRI) */
7057
7058 cp = (char *) data;
7059 if (!*cp) {
7060 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
7061 x = 0;
7063 } else {
7064 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
7065 x = 1;
7066 }
7067 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
7068 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
7069 break;
7070 case AST_OPTION_OPRMODE: /* Operator services mode */
7071 oprmode = (struct oprmode *) data;
7072 /* We don't support operator mode across technologies */
7073 if (strcasecmp(ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type)) {
7074 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
7076 errno = EINVAL;
7077 return -1;
7078 }
7080 p->oprmode = pp->oprmode = 0;
7081 /* setup peers */
7082 p->oprpeer = pp;
7083 pp->oprpeer = p;
7084 /* setup modes, if any */
7085 if (oprmode->mode)
7086 {
7087 pp->oprmode = oprmode->mode;
7088 p->oprmode = -oprmode->mode;
7089 }
7090 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
7092 break;
7093 case AST_OPTION_ECHOCAN:
7094 cp = (char *) data;
7095 if (*cp) {
7096 ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
7097 dahdi_ec_enable(p);
7098 } else {
7099 ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
7101 }
7102 break;
7104 cp = (char *) data;
7105 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
7106 if (*cp) {
7108 } else {
7110 }
7111 break;
7113 cp = (char *) data;
7114 if (p->dsp) {
7115 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
7116 if (*cp) {
7118 } else {
7119 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
7120 }
7122 }
7123 break;
7124 default:
7125 return -1;
7126 }
7127 errno = 0;
7128
7129 return 0;
7130}
void dahdi_dtmf_detect_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:6847
void dahdi_dtmf_detect_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:6833
#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:649
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 16172 of file chan_dahdi.c.

16173{
16174 int channel;
16175 struct dahdi_pvt *tmp = NULL;
16176 struct dahdi_confinfo ci;
16177 struct dahdi_params ps;
16178 int x;
16179 char hwrxgain[15];
16180 char hwtxgain[15];
16181
16182 switch (cmd) {
16183 case CLI_INIT:
16184 e->command = "dahdi show channel";
16185 e->usage =
16186 "Usage: dahdi show channel <chan num>\n"
16187 " Detailed information about a given channel\n";
16188 return NULL;
16189 case CLI_GENERATE:
16190 return NULL;
16191 }
16192
16193 if (a->argc != 4)
16194 return CLI_SHOWUSAGE;
16195
16196 channel = atoi(a->argv[3]);
16197
16199 for (tmp = iflist; tmp; tmp = tmp->next) {
16200 if (tmp->channel == channel) {
16201 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
16202 ast_cli(a->fd, "Description: %s\n", tmp->description);
16203 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
16204 ast_cli(a->fd, "Span: %d\n", tmp->span);
16205 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
16206 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
16207 ast_cli(a->fd, "Context: %s\n", tmp->context);
16208 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
16209 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
16210#if defined(HAVE_PRI)
16211#if defined(HAVE_PRI_SUBADDR)
16212 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
16213#endif /* defined(HAVE_PRI_SUBADDR) */
16214#endif /* defined(HAVE_PRI) */
16215 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
16216 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
16217 if (tmp->vars) {
16218 struct ast_variable *v;
16219 ast_cli(a->fd, "Variables:\n");
16220 for (v = tmp->vars ; v ; v = v->next)
16221 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
16222 }
16223 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
16224 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
16225 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
16226 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
16227 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? ast_channel_name(tmp->owner) : "<None>");
16228 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)" : "");
16229 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)" : "");
16230 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)" : "");
16231 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
16232 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
16233 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
16234 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
16235 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
16236 if (tmp->busydetect) {
16237#if defined(BUSYDETECT_TONEONLY)
16238 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
16239#elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
16240 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
16241#endif
16242#ifdef BUSYDETECT_DEBUG
16243 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
16244#endif
16245 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
16246 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);
16247 }
16248 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
16249 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
16250 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
16251 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
16252 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
16253 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
16254 if (tmp->hwrxgain_enabled) {
16255 snprintf(hwrxgain, sizeof(hwrxgain), "%.1f", tmp->hwrxgain);
16256 } else {
16257 ast_copy_string(hwrxgain, "Disabled", sizeof(hwrxgain));
16258 }
16259 if (tmp->hwtxgain_enabled) {
16260 snprintf(hwtxgain, sizeof(hwtxgain), "%.1f", tmp->hwtxgain);
16261 } else {
16262 ast_copy_string(hwtxgain, "Disabled", sizeof(hwtxgain));
16263 }
16264 ast_cli(a->fd, "HW Gains (RX/TX): %s/%s\n", hwrxgain, hwtxgain);
16265 ast_cli(a->fd, "SW Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
16266 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
16267 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
16268 ast_cli(a->fd, "Echo Cancellation:\n");
16269
16270 if (tmp->echocancel.head.tap_length) {
16271 ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length);
16272 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
16273 ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
16274 }
16275 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
16276 } else {
16277 ast_cli(a->fd, "\tnone\n");
16278 }
16279 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
16280 if (tmp->master)
16281 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
16282 for (x = 0; x < MAX_SLAVES; x++) {
16283 if (tmp->slaves[x])
16284 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
16285 }
16286#ifdef HAVE_OPENR2
16287 if (tmp->mfcr2) {
16288 char calldir[OR2_MAX_PATH];
16289 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
16290 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
16291 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
16292 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
16293 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
16294 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
16295 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
16296 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
16297 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
16298 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
16299#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
16300 ast_cli(a->fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
16301 ast_cli(a->fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
16302#endif
16303 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
16304#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
16305 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
16306#endif
16307 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
16308 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
16309 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
16310 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
16311 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
16312 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
16313 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
16314 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
16315 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
16316 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
16317 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
16318 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
16319 }
16320#endif
16321#if defined(HAVE_SS7)
16322 if (tmp->ss7) {
16323 struct sig_ss7_chan *chan = tmp->sig_pvt;
16324
16325 ast_cli(a->fd, "CIC: %d\n", chan->cic);
16326 }
16327#endif /* defined(HAVE_SS7) */
16328#ifdef HAVE_PRI
16329 if (tmp->pri) {
16330 struct sig_pri_chan *chan = tmp->sig_pvt;
16331
16332 ast_cli(a->fd, "PRI Flags: ");
16333 if (chan->resetting != SIG_PRI_RESET_IDLE) {
16334 ast_cli(a->fd, "Resetting=%u ", chan->resetting);
16335 }
16336 if (chan->call)
16337 ast_cli(a->fd, "Call ");
16338 if (chan->allocated) {
16339 ast_cli(a->fd, "Allocated ");
16340 }
16341 ast_cli(a->fd, "\n");
16342 if (tmp->logicalspan)
16343 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
16344 else
16345 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
16346 }
16347#endif
16348 memset(&ci, 0, sizeof(ci));
16349 ps.channo = tmp->channel;
16350 if (tmp->subs[SUB_REAL].dfd > -1) {
16351 memset(&ci, 0, sizeof(ci));
16352 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
16353 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode);
16354 }
16355 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
16356 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
16357 }
16358 memset(&ps, 0, sizeof(ps));
16359 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
16360 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
16361 } else {
16362 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
16363 }
16364 }
16366 return CLI_SUCCESS;
16367 }
16368 }
16370
16371 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16372 return CLI_FAILURE;
16373}
@ SIG_PRI_RESET_IDLE
The channel is not being RESTARTed.
Definition: sig_pri.h:154
int pattern[4]
Definition: dsp.h:68
char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Voice mailbox location.
Definition: chan_dahdi.h:715
struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS]
Definition: chan_dahdi.h:634
unsigned int echocanbridged
TRUE if echo cancellation enabled when bridged.
Definition: chan_dahdi.h:270
int propconfno
Definition: chan_dahdi.h:565
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, dahdi_pvt::busy_cadence, dahdi_pvt::busycount, dahdi_pvt::busydetect, sig_pri_chan::call, dahdi_pvt::callwaitcas, dahdi_pvt::channel, sig_pri_chan::channel, sig_ss7_chan::cic, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_ton, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_pvt::confno, dahdi_pvt::context, dahdi_dnd(), dahdi_pvt::description, dahdi_pvt::destroy, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, dahdi_pvt::head, dahdi_pvt::hwrxgain, dahdi_pvt::hwrxgain_enabled, dahdi_pvt::hwtxgain, dahdi_pvt::hwtxgain_enabled, iflist, iflock, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pvt::law_default, ast_dsp_busy_pattern::length, dahdi_subchannel::linear, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::master, MAX_SLAVES, ast_variable::name, dahdi_pvt::next, ast_variable::next, NULL, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::params, ast_dsp_busy_pattern::pattern, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::radio, sig_pri_chan::resetting, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, S_OR, dahdi_pvt::sig, sig2str, SIG_PRI_RESET_IDLE, dahdi_pvt::sig_pvt, dahdi_pvt::slaves, dahdi_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, dahdi_pvt::tdd, dahdi_pvt::txdrc, dahdi_pvt::txgain, ast_cli_entry::usage, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

◆ dahdi_show_channels()

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

Definition at line 16091 of file chan_dahdi.c.

16092{
16093#define FORMAT "%7s %4d %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"
16094#define FORMAT2 "%7s %4s %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"
16095 ast_group_t targetnum = 0;
16096 int filtertype = 0;
16097 struct dahdi_pvt *tmp = NULL;
16098 char tmps[20];
16099 char blockstr[20];
16100
16101 switch (cmd) {
16102 case CLI_INIT:
16103 e->command = "dahdi show channels [group|context]";
16104 e->usage =
16105 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
16106 " Shows a list of available channels with optional filtering\n"
16107 " <group> must be a number between 0 and 63\n";
16108 return NULL;
16109 case CLI_GENERATE:
16110 return NULL;
16111 }
16112
16113 /* syntax: dahdi show channels [ group <group> | context <context> ] */
16114
16115 if (!((a->argc == 3) || (a->argc == 5))) {
16116 return CLI_SHOWUSAGE;
16117 }
16118
16119 if (a->argc == 5) {
16120 if (!strcasecmp(a->argv[3], "group")) {
16121 targetnum = atoi(a->argv[4]);
16122 if (63 < targetnum) {
16123 return CLI_SHOWUSAGE;
16124 }
16125 targetnum = ((ast_group_t) 1) << targetnum;
16126 filtertype = 1;
16127 } else if (!strcasecmp(a->argv[3], "context")) {
16128 filtertype = 2;
16129 }
16130 }
16131
16132 ast_cli(a->fd, FORMAT2, "Chan", "Span", "Signalling", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "In Service", "Alarms", "Description");
16134 for (tmp = iflist; tmp; tmp = tmp->next) {
16135 int alm = 0;
16136 if (filtertype) {
16137 switch(filtertype) {
16138 case 1: /* dahdi show channels group <group> */
16139 if (!(tmp->group & targetnum)) {
16140 continue;
16141 }
16142 break;
16143 case 2: /* dahdi show channels context <context> */
16144 if (strcasecmp(tmp->context, a->argv[4])) {
16145 continue;
16146 }
16147 break;
16148 default:
16149 break;
16150 }
16151 }
16152 if (tmp->channel > 0) {
16153 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
16154 alm = get_alarms(tmp);
16155 } else {
16156 ast_copy_string(tmps, "pseudo", sizeof(tmps));
16157 }
16158
16159 blockstr[0] = tmp->locallyblocked ? 'L' : ' ';
16160 blockstr[1] = tmp->remotelyblocked ? 'R' : ' ';
16161 blockstr[2] = '\0';
16162
16163 ast_cli(a->fd, FORMAT, tmps, tmp->span, sig2str(tmp->sig), tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, tmp->inservice ? "Yes" : "No",
16164 alarm2str(alm), tmp->description);
16165 }
16167 return CLI_SUCCESS;
16168#undef FORMAT
16169#undef FORMAT2
16170}
#define FORMAT
#define FORMAT2
unsigned long long ast_group_t
Definition: channel.h:215
unsigned int inservice
TRUE if channel is out of reset and ready.
Definition: chan_dahdi.h:446

References a, alarm2str(), ast_cli(), ast_copy_string(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_pvt::context, dahdi_pvt::description, dahdi_pvt::exten, FORMAT, FORMAT2, get_alarms(), dahdi_pvt::group, iflist, iflock, dahdi_pvt::inservice, dahdi_pvt::language, dahdi_pvt::locallyblocked, dahdi_pvt::mohinterpret, dahdi_pvt::next, NULL, dahdi_pvt::remotelyblocked, dahdi_pvt::sig, sig2str, dahdi_pvt::span, 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 16450 of file chan_dahdi.c.

16451{
16452 #define FORMAT "%4d %-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
16453 #define FORMAT2 "%4s %-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
16454 int span;
16455 int res;
16456 char alarmstr[50];
16457
16458 int ctl;
16459 struct dahdi_spaninfo s;
16460
16461 switch (cmd) {
16462 case CLI_INIT:
16463 e->command = "dahdi show status";
16464 e->usage =
16465 "Usage: dahdi show status\n"
16466 " Shows a list of DAHDI cards with status\n";
16467 return NULL;
16468 case CLI_GENERATE:
16469 return NULL;
16470 }
16471 ctl = open("/dev/dahdi/ctl", O_RDWR);
16472 if (ctl < 0) {
16473 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
16474 return CLI_FAILURE;
16475 }
16476 ast_cli(a->fd, FORMAT2, "Span", "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
16477
16478 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
16479 s.spanno = span;
16480 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
16481 if (res) {
16482 continue;
16483 }
16484 build_alarm_info(alarmstr, &s);
16485 ast_cli(a->fd, FORMAT, span, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
16486 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
16487 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
16488 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
16489 "CAS",
16490 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
16491 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
16492 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
16493 "Unknown",
16494 s.lineconfig & DAHDI_CONFIG_CRC4 ?
16495 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
16496 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
16497 lbostr[s.lbo]
16498 );
16499 }
16500 close(ctl);
16501
16502 return CLI_SUCCESS;
16503#undef FORMAT
16504#undef FORMAT2
16505}

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

16508{
16509 int pseudo_fd = -1;
16510 struct dahdi_versioninfo vi;
16511
16512 switch (cmd) {
16513 case CLI_INIT:
16514 e->command = "dahdi show version";
16515 e->usage =
16516 "Usage: dahdi show version\n"
16517 " Shows the DAHDI version in use\n";
16518 return NULL;
16519 case CLI_GENERATE:
16520 return NULL;
16521 }
16522 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
16523 ast_cli(a->fd, "Failed to open control file to get version.\n");
16524 return CLI_SUCCESS;
16525 }
16526
16527 strcpy(vi.version, "Unknown");
16528 strcpy(vi.echo_canceller, "Unknown");
16529
16530 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
16531 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
16532 else
16533 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16534
16535 close(pseudo_fd);
16536
16537 return CLI_SUCCESS;
16538}

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

4722{
4723 static char buf[256];
4724 switch (sig) {
4725 case SIG_EM:
4726 return "E & M Immediate";
4727 case SIG_EMWINK:
4728 return "E & M Wink";
4729 case SIG_EM_E1:
4730 return "E & M E1";
4731 case SIG_FEATD:
4732 return "Feature Group D (DTMF)";
4733 case SIG_FEATDMF:
4734 return "Feature Group D (MF)";
4735 case SIG_FEATDMF_TA:
4736 return "Feature Group D (MF) Tandem Access";
4737 case SIG_FEATB:
4738 return "Feature Group B (MF)";
4739 case SIG_E911:
4740 return "E911 (MF)";
4741 case SIG_FGC_CAMA:
4742 return "FGC/CAMA (Dialpulse)";
4743 case SIG_FGC_CAMAMF:
4744 return "FGC/CAMA (MF)";
4745 case SIG_FXSLS:
4746 return "FXS Loopstart";
4747 case SIG_FXSGS:
4748 return "FXS Groundstart";
4749 case SIG_FXSKS:
4750 return "FXS Kewlstart";
4751 case SIG_FXOLS:
4752 return "FXO Loopstart";
4753 case SIG_FXOGS:
4754 return "FXO Groundstart";
4755 case SIG_FXOKS:
4756 return "FXO Kewlstart";
4757 case SIG_PRI:
4758 return "ISDN PRI";
4759 case SIG_BRI:
4760 return "ISDN BRI Point to Point";
4761 case SIG_BRI_PTMP:
4762 return "ISDN BRI Point to MultiPoint";
4763 case SIG_SS7:
4764 return "SS7";
4765 case SIG_MFCR2:
4766 return "MFC/R2";
4767 case SIG_SF:
4768 return "SF (Tone) Immediate";
4769 case SIG_SFWINK:
4770 return "SF (Tone) Wink";
4771 case SIG_SF_FEATD:
4772 return "SF (Tone) with Feature Group D (DTMF)";
4773 case SIG_SF_FEATDMF:
4774 return "SF (Tone) with Feature Group D (MF)";
4775 case SIG_SF_FEATB:
4776 return "SF (Tone) with Feature Group B (MF)";
4777 case 0:
4778 return "Pseudo";
4779 default:
4780 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
4781 return buf;
4782 }
4783}
#define SIG_BRI
Definition: chan_dahdi.h:807
#define SIG_BRI_PTMP
Definition: chan_dahdi.h:808

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

15916{
15917 struct dahdi_pvt *p;
15918retry:
15920 for (p = iflist; p; p = p->next) {
15921 ast_mutex_lock(&p->lock);
15922 if (p->owner && !p->restartpending) {
15923 if (ast_channel_trylock(p->owner)) {
15924 if (DEBUG_ATLEAST(3))
15925 ast_verbose("Avoiding deadlock\n");
15926 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15929 goto retry;
15930 }
15931 if (DEBUG_ATLEAST(3))
15932 ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15934 p->restartpending = 1;
15937 }
15939 }
15941}
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2427
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 5023 of file chan_dahdi.c.

5024{
5025 int x;
5026 int res;
5027
5028 if (p && p->echocanon && p->echotraining) {
5029 x = p->echotraining;
5030 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
5031 if (res)
5032 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
5033 else
5034 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
5035 } else {
5036 ast_debug(1, "No echo training requested\n");
5037 }
5038}

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

853{
854 int i, j = 0;
855 i = DAHDI_IOMUX_SIGEVENT;
856 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
857 return -1;
858 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
859 return -1;
860 return j;
861}

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

9890{
9891 int j;
9892 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
9893 for (;;)
9894 {
9895 /* set bits of interest */
9896 j = DAHDI_IOMUX_SIGEVENT;
9897 /* wait for some happening */
9898 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
9899 /* exit loop if we have it */
9900 if (j & DAHDI_IOMUX_SIGEVENT) break;
9901 }
9902 /* get the event info */
9903 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
9904 return 0;
9905}

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

9342{
9343 struct dahdi_pvt *p;
9344 int res;
9345 int idx;
9346
9347 /* Write a frame of (presumably voice) data */
9348 if (frame->frametype != AST_FRAME_VOICE) {
9349 if (frame->frametype != AST_FRAME_IMAGE) {
9350 ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n",
9351 frame->frametype);
9352 }
9353 return 0;
9354 }
9355
9356 /* Return if it's not valid data */
9357 if (!frame->data.ptr || !frame->datalen) {
9358 return 0;
9359 }
9360
9361 p = ast_channel_tech_pvt(ast);
9362 ast_mutex_lock(&p->lock);
9363
9364 idx = dahdi_get_index(ast, p, 0);
9365 if (idx < 0) {
9367 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
9368 return -1;
9369 }
9370
9371 if (p->sig == SIG_FXOLS || p->sig == SIG_FXOKS || p->sig == SIG_FXOGS) {
9372 struct analog_pvt *analog_p = p->sig_pvt;
9373 if (analog_p->callwaitingdeluxepending) {
9374 unsigned int mssinceflash = ast_tvdiff_ms(ast_tvnow(), analog_p->flashtime);
9375 if (mssinceflash >= 1000) {
9376 /* Timer expired: the user hasn't yet selected an option. Take the default action and get on with it. */
9377 /* Note: If in the future Advanced Call Waiting Deluxe (*76) is supported, then as part of the
9378 * dialing code, we'll need to automatically invoke the preselected behavior about 2-3 seconds after
9379 * the call waiting begins (this allows for the SAS, CAS, and CWCID spill to be sent first).
9380 */
9381 analog_p->callwaitingdeluxepending = 0;
9382 analog_callwaiting_deluxe(analog_p, 0);
9383 }
9385 /* The user shouldn't hear anything after hook flashing, until a decision is made, by the user or when the timer expires. */
9386 ast_debug(5, "Dropping frame since Call Waiting Deluxe pending on %s\n", ast_channel_name(ast));
9387 return 0;
9388 }
9389 }
9390
9391 if (p->dialing) {
9393 ast_debug(5, "Dropping frame since I'm still dialing on %s...\n",
9394 ast_channel_name(ast));
9395 return 0;
9396 }
9397 if (!p->owner) {
9399 ast_debug(5, "Dropping frame since there is no active owner on %s...\n",
9400 ast_channel_name(ast));
9401 return 0;
9402 }
9403 if (p->cidspill) {
9405 ast_debug(5, "Dropping frame since I've still got a callerid spill on %s...\n",
9406 ast_channel_name(ast));
9407 return 0;
9408 }
9409
9411 if (!p->subs[idx].linear) {
9412 p->subs[idx].linear = 1;
9413 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9414 if (res)
9415 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
9416 }
9417 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
9420 /* x-law already */
9421 if (p->subs[idx].linear) {
9422 p->subs[idx].linear = 0;
9423 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9424 if (res)
9425 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
9426 }
9427 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
9428 } else {
9430 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n",
9432 return -1;
9433 }
9435 if (res < 0) {
9436 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
9437 return -1;
9438 }
9439 return 0;
9440}
static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
Definition: chan_dahdi.c:9319
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
int analog_callwaiting_deluxe(struct analog_pvt *p, int option)
Definition: sig_analog.c:1619
unsigned int callwaitingdeluxepending
TRUE if a Call Waiting Deluxe action is currently pending.
Definition: sig_analog.h:355
struct timeval flashtime
Definition: sig_analog.h:373

References analog_callwaiting_deluxe(), 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, ast_tvdiff_ms(), ast_tvnow(), analog_pvt::callwaitingdeluxepending, dahdi_pvt::channel, dahdi_pvt::cidspill, dahdi_get_index, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialing, errno, analog_pvt::flashtime, ast_frame_subclass::format, ast_frame::frametype, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_WARNING, my_dahdi_write(), dahdi_pvt::owner, ast_frame::ptr, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, dahdi_pvt::sig_pvt, 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 1980 of file chan_dahdi.c.

1981{
1982 RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
1983 struct ast_channel_blob *obj = stasis_message_data(msg);
1984 struct ast_json *group, *span, *channel;
1985
1986 channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1987 if (!channel_string) {
1988 return NULL;
1989 }
1990
1991 group = ast_json_object_get(obj->blob, "group");
1992 span = ast_json_object_get(obj->blob, "span");
1993 channel = ast_json_object_get(obj->blob, "channel");
1994
1995 return ast_manager_event_blob_create(EVENT_FLAG_CALL, "DAHDIChannel",
1996 "%s"
1997 "DAHDIGroup: %llu\r\n"
1998 "DAHDISpan: %u\r\n"
1999 "DAHDIChannel: %s\r\n",
2000 ast_str_buffer(channel_string),
2002 (unsigned int)ast_json_integer_get(span),
2003 ast_json_string_get(channel));
2004}
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:10239
#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 2676 of file chan_dahdi.c.

2677{
2678 enum analog_event res;
2679
2680 switch (event) {
2681 case DAHDI_EVENT_ONHOOK:
2682 res = ANALOG_EVENT_ONHOOK;
2683 break;
2684 case DAHDI_EVENT_RINGOFFHOOK:
2686 break;
2687 case DAHDI_EVENT_WINKFLASH:
2689 break;
2690 case DAHDI_EVENT_ALARM:
2691 res = ANALOG_EVENT_ALARM;
2692 break;
2693 case DAHDI_EVENT_NOALARM:
2695 break;
2696 case DAHDI_EVENT_DIALCOMPLETE:
2698 break;
2699 case DAHDI_EVENT_RINGERON:
2701 break;
2702 case DAHDI_EVENT_RINGEROFF:
2704 break;
2705 case DAHDI_EVENT_HOOKCOMPLETE:
2707 break;
2708 case DAHDI_EVENT_PULSE_START:
2710 break;
2711 case DAHDI_EVENT_POLARITY:
2713 break;
2714 case DAHDI_EVENT_RINGBEGIN:
2716 break;
2717 case DAHDI_EVENT_EC_DISABLED:
2719 break;
2720 case DAHDI_EVENT_REMOVED:
2722 break;
2723 case DAHDI_EVENT_NEONMWI_ACTIVE:
2725 break;
2726 case DAHDI_EVENT_NEONMWI_INACTIVE:
2728 break;
2729#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
2730 case DAHDI_EVENT_TX_CED_DETECTED:
2732 break;
2733 case DAHDI_EVENT_RX_CED_DETECTED:
2735 break;
2736 case DAHDI_EVENT_EC_NLP_DISABLED:
2738 break;
2739 case DAHDI_EVENT_EC_NLP_ENABLED:
2741 break;
2742#endif
2743 case DAHDI_EVENT_PULSEDIGIT:
2745 break;
2746 case DAHDI_EVENT_DTMFDOWN:
2748 break;
2749 case DAHDI_EVENT_DTMFUP:
2750 res = ANALOG_EVENT_DTMFUP;
2751 break;
2752 default:
2753 switch(event & 0xFFFF0000) {
2754 case DAHDI_EVENT_PULSEDIGIT:
2755 case DAHDI_EVENT_DTMFDOWN:
2756 case DAHDI_EVENT_DTMFUP:
2757 /* The event includes a digit number in the low word.
2758 * Converting it to a 'enum analog_event' would remove
2759 * that information. Thus it is returned as-is.
2760 */
2761 return event;
2762 }
2763
2764 res = ANALOG_EVENT_ERROR;
2765 break;
2766 }
2767
2768 return res;
2769}
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 1252 of file chan_dahdi.c.

1253{
1254 switch (sig) {
1255 case SIG_FXOLS:
1256 return ANALOG_SIG_FXOLS;
1257 case SIG_FXOGS:
1258 return ANALOG_SIG_FXOGS;
1259 case SIG_FXOKS:
1260 return ANALOG_SIG_FXOKS;
1261 case SIG_FXSLS:
1262 return ANALOG_SIG_FXSLS;
1263 case SIG_FXSGS:
1264 return ANALOG_SIG_FXSGS;
1265 case SIG_FXSKS:
1266 return ANALOG_SIG_FXSKS;
1267 case SIG_EMWINK:
1268 return ANALOG_SIG_EMWINK;
1269 case SIG_EM:
1270 return ANALOG_SIG_EM;
1271 case SIG_EM_E1:
1272 return ANALOG_SIG_EM_E1;
1273 case SIG_FEATD:
1274 return ANALOG_SIG_FEATD;
1275 case SIG_FEATDMF:
1276 return ANALOG_SIG_FEATDMF;
1277 case SIG_E911:
1278 return SIG_E911;
1279 case SIG_FGC_CAMA:
1280 return ANALOG_SIG_FGC_CAMA;
1281 case SIG_FGC_CAMAMF:
1282 return ANALOG_SIG_FGC_CAMAMF;
1283 case SIG_FEATB:
1284 return ANALOG_SIG_FEATB;
1285 case SIG_SFWINK:
1286 return ANALOG_SIG_SFWINK;
1287 case SIG_SF:
1288 return ANALOG_SIG_SF;
1289 case SIG_SF_FEATD:
1290 return ANALOG_SIG_SF_FEATD;
1291 case SIG_SF_FEATDMF:
1292 return ANALOG_SIG_SF_FEATDMF;
1293 case SIG_FEATDMF_TA:
1294 return ANALOG_SIG_FEATDMF_TA;
1295 case SIG_SF_FEATB:
1296 return ANALOG_SIG_FEATB;
1297 default:
1298 return -1;
1299 }
1300}
@ 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 20040 of file chan_dahdi.c.

20041{
20042 struct ast_cc_config_params *cc_params;
20043
20044 cc_params = dest->chan.cc_params;
20045 *dest = *src;
20046 dest->chan.cc_params = cc_params;
20048}

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

5996{
5997 int chan;
5998#if defined(HAVE_PRI)
5999 unsigned span;
6000 struct sig_pri_span *pri;
6001#endif /* defined(HAVE_PRI) */
6002 struct dahdi_pvt *p;
6003
6004 while (num_restart_pending) {
6005 usleep(1);
6006 }
6007
6009 /* Destroy all the interfaces and free their memory */
6010 while (iflist) {
6011 p = iflist;
6012
6013 chan = p->channel;
6014#if defined(HAVE_PRI_SERVICE_MESSAGES)
6015 {
6016 char db_chan_name[20];
6017 char db_answer[5];
6018 char state;
6019 int why = -1;
6020
6021 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
6022 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
6023 sscanf(db_answer, "%1c:%30d", &state, &why);
6024 }
6025 if (!why) {
6026 /* SRVST persistence is not required */
6027 ast_db_del(db_chan_name, SRVST_DBKEY);
6028 }
6029 }
6030#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
6031 /* Free associated memory */
6033 ast_verb(3, "Unregistered channel %d\n", chan);
6034 }
6035 ifcount = 0;
6037
6038#if defined(HAVE_PRI)
6039 /* Destroy all of the no B channel interface lists */
6040 for (span = 0; span < NUM_SPANS; ++span) {
6041 if (!pris[span].dchannels[0]) {
6042 break;
6043 }
6044 pri = &pris[span].pri;
6045 ast_mutex_lock(&pri->lock);
6046 while (pri->no_b_chan_iflist) {
6047 p = pri->no_b_chan_iflist;
6048
6049 /* Free associated memory */
6051 }
6052 ast_mutex_unlock(&pri->lock);
6053 }
6054#endif /* defined(HAVE_PRI) */
6055}
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: db.c:421
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: db.c:472
enum cc_state state
Definition: ccss.c:399
static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5897
static int ifcount
Definition: chan_dahdi.c:819
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 5977 of file chan_dahdi.c.

5978{
5979 int i;
5980
5981 if (!now) {
5982 /* Do not destroy the channel now if it is owned by someone. */
5983 if (cur->owner) {
5984 return;
5985 }
5986 for (i = 0; i < 3; i++) {
5987 if (cur->subs[i].owner) {
5988 return;
5989 }
5990 }
5991 }
5992 destroy_dahdi_pvt(cur);
5993}

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

5898{
5899 struct dahdi_pvt *p = pvt;
5900
5901 if (p->manages_span_alarms) {
5903 if (next) {
5905 }
5906 }
5907
5908 /* Remove channel from the list */
5909#if defined(HAVE_PRI)
5910 dahdi_unlink_pri_pvt(p);
5911#endif /* defined(HAVE_PRI) */
5912#if defined(HAVE_SS7)
5913 dahdi_unlink_ss7_pvt(p);
5914#endif /* defined(HAVE_SS7) */
5915#if defined(HAVE_OPENR2)
5916 dahdi_unlink_mfcr2_pvt(p);
5917#endif /* defined(HAVE_SS7) */
5918 switch (pvt->which_iflist) {
5919 case DAHDI_IFLIST_NONE:
5920 break;
5921 case DAHDI_IFLIST_MAIN:
5923 break;
5924#if defined(HAVE_PRI)
5925 case DAHDI_IFLIST_NO_B_CHAN:
5926 if (p->pri) {
5927 dahdi_nobch_extract(p->pri, p);
5928 }
5929 break;
5930#endif /* defined(HAVE_PRI) */
5931 }
5932
5933 if (p->sig_pvt) {
5934 if (dahdi_analog_lib_handles(p->sig, 0, 0)) {
5936 }
5937 switch (p->sig) {
5938#if defined(HAVE_PRI)
5941 break;
5942#endif /* defined(HAVE_PRI) */
5943#if defined(HAVE_SS7)
5944 case SIG_SS7:
5946 break;
5947#endif /* defined(HAVE_SS7) */
5948 default:
5949 break;
5950 }
5951 }
5952 ast_free(p->cidspill);
5953 if (p->use_smdi) {
5955 }
5956 if (p->mwi_event_sub) {
5958 }
5959 if (p->vars) {
5961 }
5962 if (p->cc_params) {
5964 }
5965
5968
5971 if (p->owner) {
5973 }
5974 ast_free(p);
5975}
static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5670
static struct dahdi_pvt * find_next_iface_in_span(struct dahdi_pvt *cur)
Definition: chan_dahdi.c:5886
struct ast_namedgroups * ast_unref_namedgroups(struct ast_namedgroups *groups)
Definition: channel.c:7705
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
#define ast_mutex_destroy(a)
Definition: lock.h:195
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:4346
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:717
unsigned int manages_span_alarms
TRUE if the channel alarms will be managed also as Span ones.
Definition: chan_dahdi.h:471

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

13845{
13846 char *dest;
13847 char *s;
13848 int x;
13849 int res = 0;
13850 struct dahdi_pvt *p;
13851 char *subdir = NULL;
13853 AST_APP_ARG(group); /* channel/group token */
13854 //AST_APP_ARG(ext); /* extension token */
13855 //AST_APP_ARG(opts); /* options token */
13856 AST_APP_ARG(other); /* Any remaining unused arguments */
13857 );
13858
13859 /*
13860 * data is ---v
13861 * Dial(DAHDI/pseudo[/extension[/options]])
13862 * Dial(DAHDI/<channel#>[c|r<cadence#>|d][/extension[/options]])
13863 * Dial(DAHDI/<subdir>!<channel#>[c|r<cadence#>|d][/extension[/options]])
13864 * Dial(DAHDI/i<span>[/extension[/options]])
13865 * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadence#>|d][/extension[/options]])
13866 *
13867 * i - ISDN span channel restriction.
13868 * Used by CC to ensure that the CC recall goes out the same span.
13869 * Also to make ISDN channel names dialable when the sequence number
13870 * is stripped off. (Used by DTMF attended transfer feature.)
13871 *
13872 * g - channel group allocation search forward
13873 * G - channel group allocation search backward
13874 * r - channel group allocation round robin search forward
13875 * R - channel group allocation round robin search backward
13876 *
13877 * c - Wait for DTMF digit to confirm answer
13878 * r<cadence#> - Set distinctive ring cadence number
13879 * d - Force bearer capability for ISDN/SS7 call to digital.
13880 */
13881
13882 if (data) {
13883 dest = ast_strdupa(data);
13884 } else {
13885 ast_log(LOG_WARNING, "Channel requested with no data\n");
13886 return NULL;
13887 }
13888 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13889 if (!args.argc || ast_strlen_zero(args.group)) {
13890 ast_log(LOG_WARNING, "No channel/group specified\n");
13891 return NULL;
13892 }
13893
13894 /* Initialize the output parameters */
13895 memset(param, 0, sizeof(*param));
13896 param->channelmatch = -1;
13897
13898 if (strchr(args.group, '!') != NULL) {
13899 char *prev = args.group;
13900 while ((s = strchr(prev, '!')) != NULL) {
13901 *s++ = '/';
13902 prev = s;
13903 }
13904 *(prev - 1) = '\0';
13905 subdir = args.group;
13906 args.group = prev;
13907 } else if (args.group[0] == 'i') {
13908 /* Extract the ISDN span channel restriction specifier. */
13909 res = sscanf(args.group + 1, "%30d", &x);
13910 if (res < 1) {
13911 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13912 return NULL;
13913 }
13914 param->span = x;
13915
13916 /* Remove the ISDN span channel restriction specifier. */
13917 s = strchr(args.group, '-');
13918 if (!s) {
13919 /* Search all groups since we are ISDN span restricted. */
13920 return iflist;
13921 }
13922 args.group = s + 1;
13923 res = 0;
13924 }
13925 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13926 /* Retrieve the group number */
13927 s = args.group + 1;
13928 res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadence);
13929 if (res < 1) {
13930 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13931 return NULL;
13932 }
13933 param->groupmatch = ((ast_group_t) 1 << x);
13934
13935 if (toupper(args.group[0]) == 'G') {
13936 if (args.group[0] == 'G') {
13937 param->backwards = 1;
13938 p = ifend;
13939 } else
13940 p = iflist;
13941 } else {
13942 if (ARRAY_LEN(round_robin) <= x) {
13943 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13944 x, data);
13945 return NULL;
13946 }
13947 if (args.group[0] == 'R') {
13948 param->backwards = 1;
13949 p = round_robin[x] ? round_robin[x]->prev : ifend;
13950 if (!p)
13951 p = ifend;
13952 } else {
13953 p = round_robin[x] ? round_robin[x]->next : iflist;
13954 if (!p)
13955 p = iflist;
13956 }
13957 param->roundrobin = 1;
13958 param->rr_starting_point = x;
13959 }
13960 } else {
13961 s = args.group;
13962 if (!strcasecmp(s, "pseudo")) {
13963 /* Special case for pseudo */
13964 x = CHAN_PSEUDO;
13965 param->channelmatch = x;
13966 } else {
13967 res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadence);
13968 if (res < 1) {
13969 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13970 return NULL;
13971 } else {
13972 param->channelmatch = x;
13973 }
13974 }
13975 if (subdir) {
13976 char path[PATH_MAX];
13977 struct stat stbuf;
13978
13979 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13980 subdir, param->channelmatch);
13981 if (stat(path, &stbuf) < 0) {
13982 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13983 path, strerror(errno));
13984 return NULL;
13985 }
13986 if (!S_ISCHR(stbuf.st_mode)) {
13987 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13988 path);
13989 return NULL;
13990 }
13991 param->channelmatch = minor(stbuf.st_rdev);
13992 }
13993
13994 p = iflist;
13995 }
13996
13997 if (param->opt == 'r' && res < 3) {
13998 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13999 param->opt = '\0';
14000 }
14001
14002 return p;
14003}
#define PATH_MAX
Definition: asterisk.h:40
ast_group_t groupmatch
Definition: chan_dahdi.c:13828

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

4552{
4553 if (isdigit(digit))
4554 return DAHDI_TONE_DTMF_BASE + (digit - '0');
4555 else if (digit >= 'A' && digit <= 'D')
4556 return DAHDI_TONE_DTMF_A + (digit - 'A');
4557 else if (digit >= 'a' && digit <= 'd')
4558 return DAHDI_TONE_DTMF_A + (digit - 'a');
4559 else if (digit == '*')
4560 return DAHDI_TONE_DTMF_s;
4561 else if (digit == '#')
4562 return DAHDI_TONE_DTMF_p;
4563 else
4564 return -1;
4565}

References digit.

Referenced by dahdi_digit_begin().

◆ do_monitor()

static void * do_monitor ( void *  data)
static

Definition at line 11952 of file chan_dahdi.c.

11953{
11954 int count, res, res2, spoint, pollres=0;
11955 struct dahdi_pvt *i;
11956 struct dahdi_pvt *last = NULL;
11957 struct dahdi_pvt *doomed;
11958 time_t thispass = 0, lastpass = 0;
11959 int found;
11960 char buf[1024];
11961 struct pollfd *pfds=NULL;
11962 int lastalloc = -1;
11963 /* This thread monitors all the frame relay interfaces which are not yet in use
11964 (and thus do not have a separate thread) indefinitely */
11965 /* From here on out, we die whenever asked */
11966#if 0
11967 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11968 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11969 return NULL;
11970 }
11971 ast_debug(1, "Monitor starting...\n");
11972#endif
11973 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11974
11975 pthread_cleanup_push(monitor_pfds_clean, &pfds);
11976 for (;;) {
11977 /* Lock the interface list */
11979 if (!pfds || (lastalloc != ifcount)) {
11980 if (pfds) {
11981 ast_free(pfds);
11982 pfds = NULL;
11983 }
11984 if (ifcount) {
11985 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11987 return NULL;
11988 }
11989 }
11990 lastalloc = ifcount;
11991 }
11992 /* Build the stuff we're going to poll on, that is the socket of every
11993 dahdi_pvt that does not have an associated owner channel */
11994 count = 0;
11995 for (i = iflist; i; i = i->next) {
11996 ast_mutex_lock(&i->lock);
11997 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11998 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11999 struct analog_pvt *p = i->sig_pvt;
12000
12001 if (!p) {
12002 ast_log(LOG_ERROR, "No sig_pvt?\n");
12003 } else if (!p->owner && !p->subs[SUB_REAL].owner) {
12004 /* This needs to be watched, as it lacks an owner */
12005 pfds[count].fd = i->subs[SUB_REAL].dfd;
12006 pfds[count].events = POLLPRI;
12007 pfds[count].revents = 0;
12008 /* Message waiting or r2 channels also get watched for reading */
12009 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
12010 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
12011 pfds[count].events |= POLLIN;
12012 }
12013 count++;
12014 }
12015 } else {
12016 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
12017 /* This needs to be watched, as it lacks an owner */
12018 pfds[count].fd = i->subs[SUB_REAL].dfd;
12019 pfds[count].events = POLLPRI;
12020 pfds[count].revents = 0;
12021 /* If we are monitoring for VMWI or sending CID, we need to
12022 read from the channel as well */
12023 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
12024 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
12025 pfds[count].events |= POLLIN;
12026 }
12027 count++;
12028 }
12029 }
12030 }
12032 }
12033 /* Okay, now that we know what to do, release the interface lock */
12035
12036 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
12037 pthread_testcancel();
12038 /* Wait at least a second for something to happen */
12039 res = poll(pfds, count, 1000);
12040 pthread_testcancel();
12041 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12042
12043 /* Okay, poll has finished. Let's see what happened. */
12044 if (res < 0) {
12045 if ((errno != EAGAIN) && (errno != EINTR))
12046 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
12047 continue;
12048 }
12049 /* Alright, lock the interface list again, and let's look and see what has
12050 happened */
12052 found = 0;
12053 spoint = 0;
12054 lastpass = thispass;
12055 thispass = time(NULL);
12056 doomed = NULL;
12057 for (i = iflist;; i = i->next) {
12058 if (doomed) {
12060 doomed = NULL;
12061 }
12062 if (!i) {
12063 break;
12064 }
12065
12066 if (thispass != lastpass) {
12067 if (!found && ((i == last) || ((i == iflist) && !last))) {
12068 last = i;
12069 if (last) {
12070 struct analog_pvt *analog_p = last->sig_pvt;
12071 /* Only allow MWI to be initiated on a quiescent fxs port */
12072 if (analog_p
12073 && !last->mwisendactive
12074 && (last->sig & __DAHDI_SIG_FXO)
12075 && !analog_p->fxsoffhookstate
12076 && !last->owner
12077 && (!ast_strlen_zero(last->mailbox) || last->mwioverride_active)
12078 && !analog_p->subs[SUB_REAL].owner /* could be a recall ring from a flash hook hold */
12079 && (thispass - analog_p->onhooktime > 3)
12080 /* In some cases, all of the above checks will pass even if the line is really off-hook.
12081 * This last check will give the right answer 100% of the time, but is relatively
12082 * "expensive" (it requires an ioctl), so it is last to avoid unnecessary system calls. */
12083 && !my_is_off_hook(last)) {
12084 res = has_voicemail(last);
12085 if (analog_p->msgstate != res) {
12086 /* Set driver resources for signalling VMWI */
12087 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
12088 if (res2) {
12089 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
12090 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
12091 }
12092 /* If enabled for FSK spill then initiate it */
12093 ast_debug(5, "Initiating MWI FSK spill on channel %d\n", last->channel);
12094 if (mwi_send_init(last)) {
12095 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
12096 }
12097 analog_p->msgstate = res;
12098 found ++;
12099 }
12100 }
12101 last = last->next;
12102 }
12103 }
12104 }
12105 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
12106 if (i->radio && !i->owner)
12107 {
12108 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12109 if (res)
12110 {
12111 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
12112 /* Don't hold iflock while handling init events */
12114 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
12116 else
12117 doomed = handle_init_event(i, res);
12119 }
12120 continue;
12121 }
12122 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
12123 if (pollres & POLLIN) {
12124 if (i->owner || i->subs[SUB_REAL].owner) {
12125#ifdef HAVE_PRI
12126 if (!i->pri)
12127#endif
12128 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
12129 continue;
12130 }
12132 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
12133 continue;
12134 }
12135 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
12136 if (res > 0) {
12137 if (i->mwimonitor_fsk) {
12138 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
12139 pthread_attr_t attr;
12140 pthread_t threadid;
12141 struct mwi_thread_data *mtd;
12142
12143 pthread_attr_init(&attr);
12144 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
12145
12146 ast_debug(1, "Maybe some MWI on port %d!\n", i->channel);
12147 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
12148 mtd->pvt = i;
12149 memcpy(mtd->buf, buf, res);
12150 mtd->len = res;
12151 i->mwimonitoractive = 1;
12152 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
12153 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
12154 i->mwimonitoractive = 0;
12155 ast_free(mtd);
12156 }
12157 }
12158 }
12159 /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
12160 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
12161 int energy;
12162 struct timeval now;
12163 /* State machine dtmfcid_holdoff_state allows for the line to settle
12164 * before checking again for dtmf energy. Presently waits for 500 mS before checking again
12165 */
12166 if (1 == i->dtmfcid_holdoff_state) {
12167 gettimeofday(&i->dtmfcid_delay, NULL);
12168 i->dtmfcid_holdoff_state = 2;
12169 } else if (2 == i->dtmfcid_holdoff_state) {
12170 gettimeofday(&now, NULL);
12171 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
12172 i->dtmfcid_holdoff_state = 0;
12173 }
12174 } else {
12175 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
12176 if (!i->mwisendactive && energy > dtmfcid_level) {
12177 pthread_t threadid;
12178 struct ast_channel *chan;
12180 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12181 /* just in case this event changes or somehow destroys a channel, set doomed here too */
12183 i->dtmfcid_holdoff_state = 1;
12184 } else {
12185 ast_callid callid = 0;
12186 int callid_created = ast_callid_threadstorage_auto(&callid);
12187 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
12188 if (!chan) {
12189 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
12190 } else {
12191 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
12192 if (res) {
12193 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
12194 ast_hangup(chan);
12195 } else {
12196 i->dtmfcid_holdoff_state = 1;
12197 }
12198 }
12200 }
12202 }
12203 }
12204 }
12205 if (i->mwisendactive) {
12207 }
12208 } else {
12209 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
12210 }
12211 }
12212 if (pollres & POLLPRI) {
12213 if (i->owner || i->subs[SUB_REAL].owner) {
12214#ifdef HAVE_PRI
12215 if (!i->pri)
12216#endif
12217 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
12218 continue;
12219 }
12220 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12221 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
12222 /* Don't hold iflock while handling init events */
12224 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
12225 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
12227 else
12228 doomed = handle_init_event(i, res);
12229 }
12230 if (i->doreoriginate && res == DAHDI_EVENT_HOOKCOMPLETE) {
12231 /* Actually automatically reoriginate this FXS line, if directed to.
12232 * We should get a DAHDI_EVENT_HOOKCOMPLETE from the loop disconnect
12233 * doing its thing (one reason why this is for FXOKS only: FXOLS
12234 * hangups don't give us any DAHDI events to piggyback off of)*/
12235 i->doreoriginate = 0;
12236 /* Double check the channel is still off-hook. There's only about a millisecond
12237 * between when doreoriginate is set high and we see that here, but just to be safe. */
12238 if (!my_is_off_hook(i)) {
12239 ast_debug(1, "Woah! Went back on hook before reoriginate could happen on channel %d\n", i->channel);
12240 } else {
12241 ast_verb(3, "Automatic reorigination on channel %d\n", i->channel);
12242 res = DAHDI_EVENT_RINGOFFHOOK; /* Pretend that the physical channel just went off hook */
12243 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12245 } else {
12246 doomed = handle_init_event(i, res);
12247 }
12248 }
12249 }
12251 }
12252 }
12253 }
12256#ifdef HAVE_OPENR2
12257 dahdi_r2_destroy_nodev();
12258#endif
12259 }
12260 /* Never reached */
12261 pthread_cleanup_pop(1);
12262 return NULL;
12263
12264}
struct sla_ringing_trunk * last
Definition: app_sla.c:338
#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:11182
static void release_doomed_pris(void)
Definition: chan_dahdi.c:1353
static enum analog_event dahdievent_to_analogevent(int event)
Definition: chan_dahdi.c:2676
static int mwi_send_init(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:11353
static void * mwi_thread(void *data)
Definition: chan_dahdi.c:11196
static int mwilevel
Definition: chan_dahdi.c:803
static int mwi_send_process_buffer(struct dahdi_pvt *pvt, int num_read)
Definition: chan_dahdi.c:11406
static int dtmfcid_level
Definition: chan_dahdi.c:804
static int mwi_send_process_event(struct dahdi_pvt *pvt, int event)
Definition: chan_dahdi.c:11494
static struct dahdi_pvt * handle_init_event(struct dahdi_pvt *i, int event)
Definition: chan_dahdi.c:11688
static void monitor_pfds_clean(void *arg)
Definition: chan_dahdi.c:11947
static int ast_fdisset(struct pollfd *pfds, int fd, int maximum, int *start)
Helper function for migrating select to poll.
Definition: channel.h:2877
void * analog_handle_init_event(struct analog_pvt *i, int event)
Definition: sig_analog.c:4034
@ 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:597
unsigned int mwisendactive
TRUE if a MWI message sending thread is active.
Definition: chan_dahdi.h:437
unsigned int mwimonitoractive
TRUE if an MWI monitor thread is currently active.
Definition: chan_dahdi.h:435
int dtmfcid_holdoff_state
Definition: chan_dahdi.h:596
unsigned int mwimonitor_fsk
TRUE if the FXO port monitors for fsk type MWI indications from the other end.
Definition: chan_dahdi.h:427
struct dahdi_pvt * pvt
Definition: chan_dahdi.c:11177
unsigned char buf[READ_SIZE]
Definition: chan_dahdi.c:11178
struct sla_ringing_trunk * next
Definition: app_sla.c:314
#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 5068 of file chan_dahdi.c.

5069{
5070 float neg;
5071 float shallow, steep;
5072 float max = SHRT_MAX;
5073
5074 neg = (sample < 0 ? -1 : 1);
5075 steep = drc*sample;
5076 shallow = neg*(max-max/drc)+(float)sample/drc;
5077 if (fabsf(steep) < fabsf(shallow)) {
5078 sample = steep;
5079 }
5080 else {
5081 sample = shallow;
5082 }
5083
5084 return sample;
5085}
#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 13780 of file chan_dahdi.c.

13781{
13782 struct dahdi_pvt *p;
13783 struct dahdi_bufferinfo bi;
13784 int res;
13785
13786 p = ast_malloc(sizeof(*p));
13787 if (!p) {
13788 return NULL;
13789 }
13790 *p = *src;
13791
13792 /* Must deep copy the cc_params. */
13794 if (!p->cc_params) {
13795 ast_free(p);
13796 return NULL;
13797 }
13799
13801 p->next = NULL;
13802 p->prev = NULL;
13803 ast_mutex_init(&p->lock);
13804 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13805 if (p->subs[SUB_REAL].dfd < 0) {
13806 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13808 return NULL;
13809 }
13810 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13811 if (!res) {
13812 bi.txbufpolicy = src->buf_policy;
13813 bi.rxbufpolicy = src->buf_policy;
13814 bi.numbufs = src->buf_no;
13815 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13816 if (res < 0) {
13817 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13818 }
13819 } else
13820 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13821 p->destroy = 1;
13823 return p;
13824}
static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5622
#define ast_mutex_init(pmutex)
Definition: lock.h:193

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

4713{
4714 static char buf[256];
4715 if ((event > -1) && (event < (ARRAY_LEN(events))) )
4716 return events[event];
4717 sprintf(buf, "Event %d", event); /* safe */
4718 return buf;
4719}
static const char *const events[]
Definition: chan_dahdi.c:4667

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

5139{
5140 int j;
5141 int k;
5142 float linear_gain = pow(10.0, gain / 20.0);
5143
5144 switch (law) {
5145 case DAHDI_LAW_ALAW:
5146 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5147 if (gain || drc) {
5148 k = AST_ALAW(j);
5149 if (drc) {
5150 k = drc_sample(k, drc);
5151 }
5152 k = (float)k * linear_gain;
5153 if (k > 32767) {
5154 k = 32767;
5155 } else if (k < -32768) {
5156 k = -32768;
5157 }
5158 g->rxgain[j] = AST_LIN2A(k);
5159 } else {
5160 g->rxgain[j] = j;
5161 }
5162 }
5163 break;
5164 case DAHDI_LAW_MULAW:
5165 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5166 if (gain || drc) {
5167 k = AST_MULAW(j);
5168 if (drc) {
5169 k = drc_sample(k, drc);
5170 }
5171 k = (float)k * linear_gain;
5172 if (k > 32767) {
5173 k = 32767;
5174 } else if (k < -32768) {
5175 k = -32768;
5176 }
5177 g->rxgain[j] = AST_LIN2MU(k);
5178 } else {
5179 g->rxgain[j] = j;
5180 }
5181 }
5182 break;
5183 }
5184}
#define AST_LIN2A(a)
Definition: alaw.h:50
static int drc_sample(int sample, float drc)
Definition: chan_dahdi.c:5068
#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 5088 of file chan_dahdi.c.

5089{
5090 int j;
5091 int k;
5092
5093 float linear_gain = pow(10.0, gain / 20.0);
5094
5095 switch (law) {
5096 case DAHDI_LAW_ALAW:
5097 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
5098 if (gain || drc) {
5099 k = AST_ALAW(j);
5100 if (drc) {
5101 k = drc_sample(k, drc);
5102 }
5103 k = (float)k * linear_gain;
5104 if (k > 32767) {
5105 k = 32767;
5106 } else if (k < -32768) {
5107 k = -32768;
5108 }
5109 g->txgain[j] = AST_LIN2A(k);
5110 } else {
5111 g->txgain[j] = j;
5112 }
5113 }
5114 break;
5115 case DAHDI_LAW_MULAW:
5116 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
5117 if (gain || drc) {
5118 k = AST_MULAW(j);
5119 if (drc) {
5120 k = drc_sample(k, drc);
5121 }
5122 k = (float)k * linear_gain;
5123 if (k > 32767) {
5124 k = 32767;
5125 } else if (k < -32768) {
5126 k = -32768;
5127 }
5128 g->txgain[j] = AST_LIN2MU(k);
5129
5130 } else {
5131 g->txgain[j] = j;
5132 }
5133 }
5134 break;
5135 }
5136}

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

16858{
16859 struct dahdi_pvt *p;
16860
16862 for (p = iflist; p; p = p->next) {
16863 if (p->channel == channel) {
16864 break;
16865 }
16866 }
16868 return p;
16869}

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

16881{
16882 int chan_num;
16883
16884 if (sscanf(channel, "%30d", &chan_num) != 1) {
16885 /* Not numeric string. */
16886 return NULL;
16887 }
16888
16889 return find_channel(chan_num);
16890}
static struct dahdi_pvt * find_channel(int channel)
Definition: chan_dahdi.c:16857

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

5887{
5888 if (cur->next && cur->next->span == cur->span) {
5889 return cur->next;
5890 } else if (cur->prev && cur->prev->span == cur->span) {
5891 return cur->prev;
5892 }
5893
5894 return NULL;
5895}

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

2913{
2914 int res;
2915 struct dahdi_params dahdip;
2916 struct dahdi_pvt *pvt = NULL;
2917
2918 if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
2919 ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", ast_channel_name(chan));
2920 return NULL;
2921 }
2922
2923 memset(&dahdip, 0, sizeof(dahdip));
2924 res = ioctl(ast_channel_fd(chan, 0), DAHDI_GET_PARAMS, &dahdip);
2925
2926 if (res) {
2927 ast_log(LOG_WARNING, "Unable to get parameters of %s: %s\n", ast_channel_name(chan), strerror(errno));
2928 return NULL;
2929 }
2930 if (!(dahdip.sigtype & __DAHDI_SIG_FXO)) {
2931 ast_log(LOG_WARNING, "%s is not FXO signalled\n", ast_channel_name(chan));
2932 return NULL;
2933 }
2934
2935 pvt = ast_channel_tech_pvt(chan);
2936 if (!dahdi_analog_lib_handles(pvt->sig, 0, 0)) {
2937 ast_log(LOG_WARNING, "Channel signalling is not analog");
2938 return NULL;
2939 }
2940
2941 return pvt;
2942}

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

7638{
7639 int res;
7640 struct dahdi_spaninfo zi;
7641 struct dahdi_params params;
7642
7643 memset(&zi, 0, sizeof(zi));
7644 zi.spanno = p->span;
7645
7646 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
7647 if (zi.alarms != DAHDI_ALARM_NONE)
7648 return zi.alarms;
7649 } else {
7650 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
7651 return 0;
7652 }
7653
7654 /* No alarms on the span. Check for channel alarms. */
7655 memset(&params, 0, sizeof(params));
7656 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
7657 return params.chan_alarms;
7658
7659 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
7660
7661 return DAHDI_ALARM_NONE;
7662}

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

7798{
7799 const char *alarm_str;
7800
7801#if defined(HAVE_PRI)
7803 return;
7804 }
7805#endif /* defined(HAVE_PRI) */
7806
7807 alarm_str = alarm2str(alms);
7809 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
7810 publish_channel_alarm(p->channel, alarm_str);
7811 }
7812
7814 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
7815 publish_span_alarm(p->span, alarm_str);
7816 }
7817}
static void publish_channel_alarm(int channel, const char *alarm_txt)
Definition: chan_dahdi.c:7778
static void publish_span_alarm(int span, const char *alarm_txt)
Definition: chan_dahdi.c:7764
static int report_alarms
Definition: chan_dahdi.c:808
#define REPORT_CHANNEL_ALARMS
Definition: chan_dahdi.c:806
#define REPORT_SPAN_ALARMS
Definition: chan_dahdi.c:807
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 3866 of file chan_dahdi.c.

3867{
3868#if defined(HAVE_PRI)
3870 return;
3871 }
3872#endif /* defined(HAVE_PRI) */
3873
3876 }
3879 }
3880}
static void publish_channel_alarm_clear(int channel)
Definition: chan_dahdi.c:3835
static void publish_span_alarm_clear(int span)
Definition: chan_dahdi.c:3853

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

16376{
16377 int i, j;
16378 switch (cmd) {
16379 case CLI_INIT:
16380 e->command = "dahdi show cadences";
16381 e->usage =
16382 "Usage: dahdi show cadences\n"
16383 " Shows all cadences currently defined\n";
16384 return NULL;
16385 case CLI_GENERATE:
16386 return NULL;
16387 }
16388 for (i = 0; i < num_cadence; i++) {
16389 char output[1024];
16390 char tmp[16], tmp2[64];
16391 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
16392 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
16393
16394 for (j = 0; j < 16; j++) {
16395 if (cadences[i].ringcadence[j] == 0)
16396 break;
16397 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
16398 if (cidrings[i] * 2 - 1 == j)
16399 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
16400 else
16401 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
16402 if (j != 0)
16403 strncat(output, ",", sizeof(output) - strlen(output) - 1);
16404 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
16405 }
16406 ast_cli(a->fd,"%s\n",output);
16407 }
16408 return CLI_SUCCESS;
16409}
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:771
static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
Definition: chan_dahdi.c:760
static int num_cadence
Definition: chan_dahdi.c:755
#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(), 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 11688 of file chan_dahdi.c.

11689{
11690 int res;
11691 pthread_t threadid;
11692 struct ast_channel *chan;
11693 ast_callid callid = 0;
11694 int callid_created;
11695
11696 /* Handle an event on a given channel for the monitor thread. */
11697
11698 switch (event) {
11699 case DAHDI_EVENT_NONE:
11700 case DAHDI_EVENT_BITSCHANGED:
11701 break;
11702 case DAHDI_EVENT_WINKFLASH:
11703 case DAHDI_EVENT_RINGOFFHOOK:
11704 if (i->inalarm) break;
11705 if (i->radio) break;
11706 /* Got a ring/answer. What kind of channel are we? */
11707 switch (i->sig) {
11708 case SIG_FXOLS:
11709 case SIG_FXOGS:
11710 case SIG_FXOKS:
11711 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11712 if (res && (errno == EBUSY)) {
11713 break;
11714 }
11715
11716 callid_created = ast_callid_threadstorage_auto(&callid);
11717
11718 /* Cancel VMWI spill */
11719 ast_free(i->cidspill);
11720 i->cidspill = NULL;
11722
11723 if (i->immediate) {
11724 dahdi_ec_enable(i);
11725 /* The channel is immediately up. Start right away */
11726 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11727 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL, NULL, callid);
11728 if (!chan) {
11729 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11730 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11731 if (res < 0)
11732 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11733 }
11734 } else {
11735 /* Check for callerid, digits, etc */
11736 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL, NULL, callid);
11737 if (chan) {
11738 if (has_voicemail(i))
11739 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11740 else
11741 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11742 if (res < 0)
11743 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11744 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11745 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11746 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11747 if (res < 0)
11748 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11749 ast_hangup(chan);
11750 }
11751 } else
11752 ast_log(LOG_WARNING, "Unable to create channel\n");
11753 }
11754
11756 break;
11757 case SIG_FXSLS:
11758 case SIG_FXSGS:
11759 case SIG_FXSKS:
11760 i->ringt = i->ringt_base;
11761 /* Fall through */
11762 case SIG_EMWINK:
11763 case SIG_FEATD:
11764 case SIG_FEATDMF:
11765 case SIG_FEATDMF_TA:
11766 case SIG_E911:
11767 case SIG_FGC_CAMA:
11768 case SIG_FGC_CAMAMF:
11769 case SIG_FEATB:
11770 case SIG_EM:
11771 case SIG_EM_E1:
11772 case SIG_SFWINK:
11773 case SIG_SF_FEATD:
11774 case SIG_SF_FEATDMF:
11775 case SIG_SF_FEATB:
11776 case SIG_SF:
11777 /* Check for callerid, digits, etc */
11778 callid_created = ast_callid_threadstorage_auto(&callid);
11779 if (i->cid_start == CID_START_POLARITY_IN) {
11780 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11781 } else {
11782 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, callid);
11783 }
11784
11785 if (!chan) {
11786 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11787 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11788 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11789 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11790 if (res < 0) {
11791 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11792 }
11793 ast_hangup(chan);
11794 }
11795
11797 break;
11798 default:
11799 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11800 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11801 if (res < 0)
11802 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11803 return NULL;
11804 }
11805 break;
11806 case DAHDI_EVENT_NOALARM:
11807 switch (i->sig) {
11808#if defined(HAVE_PRI)
11810 ast_mutex_lock(&i->lock);
11813 break;
11814#endif /* defined(HAVE_PRI) */
11815#if defined(HAVE_SS7)
11816 case SIG_SS7:
11818 break;
11819#endif /* defined(HAVE_SS7) */
11820 default:
11821 i->inalarm = 0;
11822 break;
11823 }
11825 break;
11826 case DAHDI_EVENT_ALARM:
11827 switch (i->sig) {
11828#if defined(HAVE_PRI)
11830 ast_mutex_lock(&i->lock);
11833 break;
11834#endif /* defined(HAVE_PRI) */
11835#if defined(HAVE_SS7)
11836 case SIG_SS7:
11838 break;
11839#endif /* defined(HAVE_SS7) */
11840 default:
11841 i->inalarm = 1;
11842 break;
11843 }
11844 res = get_alarms(i);
11845 handle_alarms(i, res);
11846 /* fall thru intentionally */
11847 case DAHDI_EVENT_ONHOOK:
11848 if (i->radio)
11849 break;
11850 /* Back on hook. Hang up. */
11851 switch (i->sig) {
11852 case SIG_FXOLS:
11853 case SIG_FXOGS:
11854 case SIG_FEATD:
11855 case SIG_FEATDMF:
11856 case SIG_FEATDMF_TA:
11857 case SIG_E911:
11858 case SIG_FGC_CAMA:
11859 case SIG_FGC_CAMAMF:
11860 case SIG_FEATB:
11861 case SIG_EM:
11862 case SIG_EM_E1:
11863 case SIG_EMWINK:
11864 case SIG_SF_FEATD:
11865 case SIG_SF_FEATDMF:
11866 case SIG_SF_FEATB:
11867 case SIG_SF:
11868 case SIG_SFWINK:
11869 case SIG_FXSLS:
11870 case SIG_FXSGS:
11871 case SIG_FXSKS:
11872 case SIG_FXOKS:
11874 /* Diddle the battery for the zhone */
11875#ifdef ZHONE_HACK
11876 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11877 usleep(1);
11878#endif
11879 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11880 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11881 break;
11882 case SIG_SS7:
11885 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11886 break;
11887 default:
11888 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11889 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11890 return NULL;
11891 }
11892 break;
11893 case DAHDI_EVENT_POLARITY:
11894 switch (i->sig) {
11895 case SIG_FXSLS:
11896 case SIG_FXSKS:
11897 case SIG_FXSGS:
11898 /* We have already got a PR before the channel was
11899 created, but it wasn't handled. We need polarity
11900 to be REV for remote hangup detection to work.
11901 At least in Spain */
11902 callid_created = ast_callid_threadstorage_auto(&callid);
11907 ast_verb(2, "Starting post polarity "
11908 "CID detection on channel %d\n",
11909 i->channel);
11910 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11911 if (!chan) {
11912 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11913 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11914 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11915 ast_hangup(chan);
11916 }
11917 }
11919 break;
11920 default:
11921 ast_log(LOG_WARNING, "handle_init_event detected "
11922 "polarity reversal on non-FXO (SIG_FXS) "
11923 "interface %d\n", i->channel);
11924 }
11925 break;
11926 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11928 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11929 i->channel);
11930 return i;
11931 case DAHDI_EVENT_NEONMWI_ACTIVE:
11932 if (i->mwimonitor_neon) {
11933 notify_message(i->mailbox, 1);
11934 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11935 }
11936 break;
11937 case DAHDI_EVENT_NEONMWI_INACTIVE:
11938 if (i->mwimonitor_neon) {
11939 notify_message(i->mailbox, 0);
11940 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11941 }
11942 break;
11943 }
11944 return NULL;
11945}
static void notify_message(char *mailbox, int thereornot)
Send MWI state change.
Definition: chan_dahdi.c:3623
unsigned int mwimonitor_neon
TRUE if the FXO port monitors for neon type MWI indications from the other end.
Definition: chan_dahdi.h:422

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

5364{
5365 int new_msgs;
5366 RAII_VAR(struct stasis_message *, mwi_message, NULL, ao2_cleanup);
5367
5368 /* A manual MWI disposition has been requested, use that instead
5369 * if this is for sending the new MWI indication. */
5370 if (p->mwioverride_active) {
5371 /* We don't clear p->mwioverride_active automatically,
5372 * because otherwise do_monitor would just change it back to the way it was.
5373 * We need to keep the override active until explicitly disabled by the user,
5374 * so that we can keep returning the correct answer in subsequent calls to do_monitor. */
5375 ast_debug(6, "MWI manual override active on channel %d: pretending that it should be %s\n",
5376 p->channel, p->mwioverride_disposition ? "active" : "inactive");
5377 return p->mwioverride_disposition;
5378 }
5379
5381 if (mwi_message) {
5382 struct ast_mwi_state *mwi_state = stasis_message_data(mwi_message);
5383 new_msgs = mwi_state->new_msgs;
5384 } else {
5386 }
5387
5388 return new_msgs;
5389}
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 13541 of file chan_dahdi.c.

13542{
13543#if defined(HAVE_PRI)
13544 if (0 < span) {
13545 /* The channel must be on the specified PRI span. */
13546 if (!p->pri || p->pri->span != span) {
13547 return 0;
13548 }
13549 if (!groupmatch && channelmatch == -1) {
13550 /* Match any group since it only needs to be on the PRI span. */
13551 *groupmatched = 1;
13552 return 1;
13553 }
13554 }
13555#endif /* defined(HAVE_PRI) */
13556 /* check group matching */
13557 if (groupmatch) {
13558 if ((p->group & groupmatch) != groupmatch)
13559 /* Doesn't match the specified group, try the next one */
13560 return 0;
13561 *groupmatched = 1;
13562 }
13563 /* Check to see if we have a channel match */
13564 if (channelmatch != -1) {
13565 if (p->channel != channelmatch)
13566 /* Doesn't match the specified channel, try the next one */
13567 return 0;
13568 *channelmatched = 1;
13569 }
13570
13571 return 1;
13572}

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

4826{
4827 /* If they're listening to our channel, they're ours */
4828 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
4829 return 1;
4830 /* If they're a talker on our (allocated) conference, they're ours */
4831 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
4832 return 1;
4833 return 0;
4834}

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

4856{
4857 int x;
4858 int useslavenative;
4859 struct dahdi_pvt *slave = NULL;
4860 /* Start out optimistic */
4861 useslavenative = 1;
4862 /* Update conference state in a stateless fashion */
4863 for (x = 0; x < 3; x++) {
4864 /* Any three-way calling makes slave native mode *definitely* out
4865 of the question */
4866 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
4867 useslavenative = 0;
4868 }
4869 /* If we don't have any 3-way calls, check to see if we have
4870 precisely one slave */
4871 if (useslavenative) {
4872 for (x = 0; x < MAX_SLAVES; x++) {
4873 if (p->slaves[x]) {
4874 if (slave) {
4875 /* Whoops already have a slave! No
4876 slave native and stop right away */
4877 slave = NULL;
4878 useslavenative = 0;
4879 break;
4880 } else {
4881 /* We have one slave so far */
4882 slave = p->slaves[x];
4883 }
4884 }
4885 }
4886 }
4887 /* If no slave, slave native definitely out */
4888 if (!slave)
4889 useslavenative = 0;
4890 else if (slave->law != p->law) {
4891 useslavenative = 0;
4892 slave = NULL;
4893 }
4894 if (out)
4895 *out = slave;
4896 return useslavenative;
4897}

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

20386{
20387 int res;
20388#if defined(HAVE_PRI) || defined(HAVE_SS7)
20389 int y;
20390#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
20391
20392 if (STASIS_MESSAGE_TYPE_INIT(dahdichannel_type)) {
20394 }
20395
20398 }
20402
20406 }
20407
20408#ifdef HAVE_PRI
20409 memset(pris, 0, sizeof(pris));
20410 for (y = 0; y < NUM_SPANS; y++) {
20411 sig_pri_init_pri(&pris[y].pri);
20412 }
20413 pri_set_error(dahdi_pri_error);
20414 pri_set_message(dahdi_pri_message);
20415 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
20416#ifdef HAVE_PRI_PROG_W_CAUSE
20417 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
20418#endif
20419#if defined(HAVE_PRI_CCSS)
20420 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
20421 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
20424 }
20425#endif /* defined(HAVE_PRI_CCSS) */
20426 if (sig_pri_load(
20427#if defined(HAVE_PRI_CCSS)
20428 dahdi_pri_cc_type
20429#else
20430 NULL
20431#endif /* defined(HAVE_PRI_CCSS) */
20432 )) {
20435 }
20436#endif
20437#if defined(HAVE_SS7)
20438 memset(linksets, 0, sizeof(linksets));
20439 for (y = 0; y < NUM_SPANS; y++) {
20440 sig_ss7_init_linkset(&linksets[y].ss7);
20441 }
20442 ss7_set_error(dahdi_ss7_error);
20443 ss7_set_message(dahdi_ss7_message);
20444 ss7_set_hangup(sig_ss7_cb_hangup);
20445 ss7_set_notinservice(sig_ss7_cb_notinservice);
20446 ss7_set_call_null(sig_ss7_cb_call_null);
20447#endif /* defined(HAVE_SS7) */
20448 res = setup_dahdi(0);
20449 /* Make sure we can register our DAHDI channel type */
20450 if (res) {
20453 }
20455 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
20458 }
20459#ifdef HAVE_PRI
20460 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
20461#endif
20462#if defined(HAVE_SS7)
20463 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
20464#endif /* defined(HAVE_SS7) */
20465#ifdef HAVE_OPENR2
20466 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
20467 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
20468#endif
20469
20471
20473 memset(round_robin, 0, sizeof(round_robin));
20474 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
20476 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
20479 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
20480 ast_manager_register_xml("DAHDIShowStatus", 0, action_dahdishowstatus);
20482#if defined(HAVE_PRI)
20483 ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
20484 ast_manager_register_xml("PRIDebugSet", 0, action_pri_debug_set);
20485 ast_manager_register_xml("PRIDebugFileSet", EVENT_FLAG_SYSTEM, action_pri_debug_file_set);
20486 ast_manager_register_xml("PRIDebugFileUnset", 0, action_pri_debug_file_unset);
20487#endif /* defined(HAVE_PRI) */
20488
20490
20491 return res;
20492}
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:1168
int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
Register a set of agent callbacks with the core.
Definition: ccss.c:1223
static int __unload_module(void)
Definition: chan_dahdi.c:18210
static int action_transfer(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16930
static int action_dahdidndon(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16892
static int action_dahdishowchannels(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:17008
static int action_dahdirestart(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16081
static int action_dahdidndoff(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16911
static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16976
static int action_transferhangup(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16953
static int action_dahdishowstatus(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:17096
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:538
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define ast_cond_init(cond, attr)
Definition: lock.h:208
#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:192
@ 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:640
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1559
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 12591 of file chan_dahdi.c.

12592{
12593 /* Make a dahdi_pvt structure for this interface */
12594 struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12595 char fn[80];
12596 struct dahdi_bufferinfo bi;
12597
12598 int res;
12599#if defined(HAVE_PRI)
12600 int span = 0;
12601#endif /* defined(HAVE_PRI) */
12602 int here = 0;/*!< TRUE if the channel interface already exists. */
12603 int x;
12604 struct analog_pvt *analog_p = NULL;
12605 struct dahdi_params p;
12606#if defined(HAVE_PRI)
12607 struct dahdi_spaninfo si;
12608 struct sig_pri_chan *pri_chan = NULL;
12609#endif /* defined(HAVE_PRI) */
12610#if defined(HAVE_SS7)
12611 struct sig_ss7_chan *ss7_chan = NULL;
12612#endif /* defined(HAVE_SS7) */
12613
12614 /* Search channel interface list to see if it already exists. */
12615 for (tmp = iflist; tmp; tmp = tmp->next) {
12616 if (!tmp->destroy) {
12617 if (tmp->channel == channel) {
12618 /* The channel interface already exists. */
12619 here = 1;
12620 break;
12621 }
12622 if (tmp->channel > channel) {
12623 /* No way it can be in the sorted list. */
12624 tmp = NULL;
12625 break;
12626 }
12627 }
12628 }
12629
12630 if (!here && reloading != 1) {
12631 tmp = ast_calloc(1, sizeof(*tmp));
12632 if (!tmp) {
12633 return NULL;
12634 }
12636 if (!tmp->cc_params) {
12637 ast_free(tmp);
12638 return NULL;
12639 }
12640 ast_mutex_init(&tmp->lock);
12641 ifcount++;
12642 for (x = 0; x < 3; x++)
12643 tmp->subs[x].dfd = -1;
12644 tmp->channel = channel;
12645 tmp->priindication_oob = conf->chan.priindication_oob;
12646 }
12647
12648 if (tmp) {
12649 int chan_sig = conf->chan.sig;
12650
12651 /* If there are variables in tmp before it is updated to match the new config, clear them */
12652 if (reloading && tmp->vars) {
12654 tmp->vars = NULL;
12655 }
12656
12657 if (!here) {
12658 /* Can only get here if this is a new channel interface being created. */
12659 if ((channel != CHAN_PSEUDO)) {
12660 int count = 0;
12661
12662 snprintf(fn, sizeof(fn), "%d", channel);
12663 /* Open non-blocking */
12664 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12665 /* Retry open on restarts, but don't keep retrying if the channel doesn't exist (e.g. not configured) */
12666 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 */
12667 usleep(1);
12668 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12669 count++;
12670 }
12671 /* Allocate a DAHDI structure */
12672 if (tmp->subs[SUB_REAL].dfd < 0) {
12673 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);
12674 destroy_dahdi_pvt(tmp);
12675 return NULL;
12676 }
12677 memset(&p, 0, sizeof(p));
12678 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12679 if (res < 0) {
12680 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12681 destroy_dahdi_pvt(tmp);
12682 return NULL;
12683 }
12684 if (conf->is_sig_auto)
12685 chan_sig = sigtype_to_signalling(p.sigtype);
12686 if (p.sigtype != (chan_sig & 0x3ffff)) {
12687 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));
12688 destroy_dahdi_pvt(tmp);
12689 return NULL;
12690 }
12691 tmp->law_default = p.curlaw;
12692 tmp->law = p.curlaw;
12693 tmp->span = p.spanno;
12694#if defined(HAVE_PRI)
12695 span = p.spanno - 1;
12696#endif /* defined(HAVE_PRI) */
12697 } else {
12698 chan_sig = 0;
12699 }
12700 tmp->sig = chan_sig;
12701 tmp->outsigmod = conf->chan.outsigmod;
12702
12703 if (dahdi_analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12704 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), tmp);
12705 if (!analog_p) {
12706 destroy_dahdi_pvt(tmp);
12707 return NULL;
12708 }
12709 tmp->sig_pvt = analog_p;
12710 }
12711#if defined(HAVE_SS7)
12712 if (chan_sig == SIG_SS7) {
12713 struct dahdi_ss7 *ss7;
12714 int clear = 0;
12715
12716 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12717 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12718 destroy_dahdi_pvt(tmp);
12719 return NULL;
12720 }
12721
12722 ss7 = ss7_resolve_linkset(cur_linkset);
12723 if (!ss7) {
12724 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12725 destroy_dahdi_pvt(tmp);
12726 return NULL;
12727 }
12728 ss7->ss7.span = cur_linkset;
12729 if (cur_cicbeginswith < 0) {
12730 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12731 destroy_dahdi_pvt(tmp);
12732 return NULL;
12733 }
12734 ss7_chan = sig_ss7_chan_new(tmp, &ss7->ss7);
12735 if (!ss7_chan) {
12736 destroy_dahdi_pvt(tmp);
12737 return NULL;
12738 }
12739 tmp->sig_pvt = ss7_chan;
12740 tmp->ss7 = &ss7->ss7;
12741
12742 ss7_chan->channel = tmp->channel;
12743 ss7_chan->cic = cur_cicbeginswith++;
12744
12745 /* DB: Add CIC's DPC information */
12746 ss7_chan->dpc = cur_defaultdpc;
12747
12748 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12749
12750 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12751 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12752 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12753 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12754 ast_copy_string(ss7->ss7.networkroutedprefix, conf->ss7.ss7.networkroutedprefix, sizeof(ss7->ss7.networkroutedprefix));
12755
12756 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12757 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12758 }
12759#endif /* defined(HAVE_SS7) */
12760#ifdef HAVE_OPENR2
12761 if (chan_sig == SIG_MFCR2) {
12762 struct dahdi_mfcr2 *r2_link;
12763 struct r2link_entry *r2_le = dahdi_r2_get_link(conf);
12764 r2_link = &r2_le->mfcr2;
12765 if (!r2_link) {
12766 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12767 destroy_dahdi_pvt(tmp);
12768 return NULL;
12769 }
12770 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12771 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12772 destroy_dahdi_pvt(tmp);
12773 return NULL;
12774 }
12775 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12776 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12777 destroy_dahdi_pvt(tmp);
12778 return NULL;
12779 }
12780 r2_link->pvts[r2_link->numchans++] = tmp;
12781 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12782 tmp->subs[SUB_REAL].dfd,
12783 NULL, NULL);
12784 if (!tmp->r2chan) {
12785 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12786 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12787 destroy_dahdi_pvt(tmp);
12788 return NULL;
12789 }
12790 r2_link->live_chans++;
12791 tmp->mfcr2 = r2_link;
12792 if (conf->mfcr2.call_files) {
12793 openr2_chan_enable_call_files(tmp->r2chan);
12794 }
12795 openr2_chan_set_client_data(tmp->r2chan, tmp);
12796 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
12797 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12798 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12799 tmp->mfcr2_category = conf->mfcr2.category;
12800 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12801 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12802 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12803 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12804 tmp->mfcr2call = 0;
12805 tmp->mfcr2_dnis_index = 0;
12806 tmp->mfcr2_ani_index = 0;
12807 }
12808#endif
12809#ifdef HAVE_PRI
12810 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12811 int offset;
12812 int matchesdchan;
12813 int x,y;
12814 int myswitchtype = 0;
12815
12816 offset = 0;
12817 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12818 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12819 destroy_dahdi_pvt(tmp);
12820 return NULL;
12821 }
12822 if (span >= NUM_SPANS) {
12823 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12824 destroy_dahdi_pvt(tmp);
12825 return NULL;
12826 } else {
12827 si.spanno = 0;
12828 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12829 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12830 destroy_dahdi_pvt(tmp);
12831 return NULL;
12832 }
12833 /* Store the logical span first based upon the real span */
12834 tmp->logicalspan = pris[span].prilogicalspan;
12835 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12836 if (span < 0) {
12837 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12838 destroy_dahdi_pvt(tmp);
12839 return NULL;
12840 }
12841 myswitchtype = conf->pri.pri.switchtype;
12842 /* Make sure this isn't a d-channel */
12843 matchesdchan=0;
12844 for (x = 0; x < NUM_SPANS; x++) {
12845 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12846 if (pris[x].dchannels[y] == tmp->channel) {
12847 matchesdchan = 1;
12848 break;
12849 }
12850 }
12851 }
12852 if (!matchesdchan) {
12853 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12854 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12855 destroy_dahdi_pvt(tmp);
12856 return NULL;
12857 }
12858 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12859 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12860 destroy_dahdi_pvt(tmp);
12861 return NULL;
12862 }
12863 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12864 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));
12865 destroy_dahdi_pvt(tmp);
12866 return NULL;
12867 }
12868 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12869 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12870 destroy_dahdi_pvt(tmp);
12871 return NULL;
12872 }
12873 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12874 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12875 destroy_dahdi_pvt(tmp);
12876 return NULL;
12877 }
12878 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12879 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12880 destroy_dahdi_pvt(tmp);
12881 return NULL;
12882 }
12883 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12884 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12885 destroy_dahdi_pvt(tmp);
12886 return NULL;
12887 }
12888 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12889 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12890 pris[span].pri.trunkgroup);
12891 destroy_dahdi_pvt(tmp);
12892 return NULL;
12893 }
12894
12895 pri_chan = sig_pri_chan_new(tmp, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12896 if (!pri_chan) {
12897 destroy_dahdi_pvt(tmp);
12898 return NULL;
12899 }
12900 tmp->sig_pvt = pri_chan;
12901 tmp->pri = &pris[span].pri;
12902
12903 tmp->priexclusive = conf->chan.priexclusive;
12904
12905 if (!tmp->pri->cc_params) {
12907 if (!tmp->pri->cc_params) {
12908 destroy_dahdi_pvt(tmp);
12909 return NULL;
12910 }
12911 }
12913 conf->chan.cc_params);
12914
12915 pris[span].pri.sig = chan_sig;
12916 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12917 pris[span].pri.switchtype = myswitchtype;
12918 pris[span].pri.nsf = conf->pri.pri.nsf;
12919 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12920 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12921 pris[span].pri.cpndialplan = conf->pri.pri.cpndialplan;
12922 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12923 pris[span].pri.minunused = conf->pri.pri.minunused;
12924 pris[span].pri.minidle = conf->pri.pri.minidle;
12925 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12926 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12927 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12928#if defined(HAVE_PRI_SERVICE_MESSAGES)
12929 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12930#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12931#ifdef HAVE_PRI_INBANDDISCONNECT
12932 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12933#endif
12934#if defined(HAVE_PRI_CALL_HOLD)
12935 pris[span].pri.hold_disconnect_transfer =
12936 conf->pri.pri.hold_disconnect_transfer;
12937#endif /* defined(HAVE_PRI_CALL_HOLD) */
12938#if defined(HAVE_PRI_CCSS)
12939 pris[span].pri.cc_ptmp_recall_mode =
12940 conf->pri.pri.cc_ptmp_recall_mode;
12941 pris[span].pri.cc_qsig_signaling_link_req =
12942 conf->pri.pri.cc_qsig_signaling_link_req;
12943 pris[span].pri.cc_qsig_signaling_link_rsp =
12944 conf->pri.pri.cc_qsig_signaling_link_rsp;
12945#endif /* defined(HAVE_PRI_CCSS) */
12946#if defined(HAVE_PRI_CALL_WAITING)
12947 pris[span].pri.max_call_waiting_calls =
12948 conf->pri.pri.max_call_waiting_calls;
12949 pris[span].pri.allow_call_waiting_calls =
12950 conf->pri.pri.allow_call_waiting_calls;
12951#endif /* defined(HAVE_PRI_CALL_WAITING) */
12952 pris[span].pri.transfer = conf->chan.transfer;
12953 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12954#if defined(HAVE_PRI_L2_PERSISTENCE)
12955 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12956#endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
12957 pris[span].pri.colp_send = conf->pri.pri.colp_send;
12958#if defined(HAVE_PRI_AOC_EVENTS)
12959 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12960 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12961#endif /* defined(HAVE_PRI_AOC_EVENTS) */
12962 if (chan_sig == SIG_BRI_PTMP) {
12963 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12964 } else {
12965 /* Option does not apply to this line type. */
12966 pris[span].pri.layer1_ignored = 0;
12967 }
12968 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12969 pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack;
12970 pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12971 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12972 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12973#if defined(HAVE_PRI_MWI)
12974 ast_copy_string(pris[span].pri.mwi_mailboxes,
12975 conf->pri.pri.mwi_mailboxes,
12976 sizeof(pris[span].pri.mwi_mailboxes));
12977 ast_copy_string(pris[span].pri.mwi_vm_boxes,
12978 conf->pri.pri.mwi_vm_boxes,
12979 sizeof(pris[span].pri.mwi_vm_boxes));
12980 ast_copy_string(pris[span].pri.mwi_vm_numbers,
12981 conf->pri.pri.mwi_vm_numbers,
12982 sizeof(pris[span].pri.mwi_vm_numbers));
12983#endif /* defined(HAVE_PRI_MWI) */
12984 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12985 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12986 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12987 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12988 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12989 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12990 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12991 pris[span].pri.moh_signaling = conf->pri.pri.moh_signaling;
12992 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12993#if defined(HAVE_PRI_DISPLAY_TEXT)
12994 pris[span].pri.display_flags_send = conf->pri.pri.display_flags_send;
12995 pris[span].pri.display_flags_receive = conf->pri.pri.display_flags_receive;
12996#endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
12997#if defined(HAVE_PRI_MCID)
12998 pris[span].pri.mcid_send = conf->pri.pri.mcid_send;
12999#endif /* defined(HAVE_PRI_MCID) */
13000 pris[span].pri.force_restart_unavailable_chans = conf->pri.pri.force_restart_unavailable_chans;
13001#if defined(HAVE_PRI_DATETIME_SEND)
13002 pris[span].pri.datetime_send = conf->pri.pri.datetime_send;
13003#endif /* defined(HAVE_PRI_DATETIME_SEND) */
13004
13005 for (x = 0; x < PRI_MAX_TIMERS; x++) {
13006 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
13007 }
13008
13009#if defined(HAVE_PRI_CALL_WAITING)
13010 /* Channel initial config parameters. */
13011 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
13012 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
13013 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
13014 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
13015 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
13016 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
13017 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
13018 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
13019 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
13020 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
13021#endif /* defined(HAVE_PRI_CALL_WAITING) */
13022 } else {
13023 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
13024 destroy_dahdi_pvt(tmp);
13025 return NULL;
13026 }
13027 }
13028 }
13029#endif
13030 } else {
13031 /* already exists in interface list */
13032 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));
13033 chan_sig = tmp->sig;
13034 if (tmp->subs[SUB_REAL].dfd > -1) {
13035 memset(&p, 0, sizeof(p));
13036 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13037 }
13038 }
13039 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
13040 switch (chan_sig) {
13041 case SIG_FXSKS:
13042 case SIG_FXSLS:
13043 case SIG_EM:
13044 case SIG_EM_E1:
13045 case SIG_EMWINK:
13046 case SIG_FEATD:
13047 case SIG_FEATDMF:
13048 case SIG_FEATDMF_TA:
13049 case SIG_FEATB:
13050 case SIG_E911:
13051 case SIG_SF:
13052 case SIG_SFWINK:
13053 case SIG_FGC_CAMA:
13054 case SIG_FGC_CAMAMF:
13055 case SIG_SF_FEATD:
13056 case SIG_SF_FEATDMF:
13057 case SIG_SF_FEATB:
13058 p.starttime = 250;
13059 break;
13060 }
13061
13062 if (tmp->radio) {
13063 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
13064 p.channo = channel;
13065 p.rxwinktime = 1;
13066 p.rxflashtime = 1;
13067 p.starttime = 1;
13068 p.debouncetime = 5;
13069 } else {
13070 p.channo = channel;
13071 /* Override timing settings based on config file */
13072 if (conf->timing.prewinktime >= 0)
13073 p.prewinktime = conf->timing.prewinktime;
13074 if (conf->timing.preflashtime >= 0)
13075 p.preflashtime = conf->timing.preflashtime;
13076 if (conf->timing.winktime >= 0)
13077 p.winktime = conf->timing.winktime;
13078 if (conf->timing.flashtime >= 0)
13079 p.flashtime = conf->timing.flashtime;
13080 if (conf->timing.starttime >= 0)
13081 p.starttime = conf->timing.starttime;
13082 if (conf->timing.rxwinktime >= 0)
13083 p.rxwinktime = conf->timing.rxwinktime;
13084 if (conf->timing.rxflashtime >= 0)
13085 p.rxflashtime = conf->timing.rxflashtime;
13086 if (conf->timing.debouncetime >= 0)
13087 p.debouncetime = conf->timing.debouncetime;
13088 }
13089
13090 /* don't set parms on a pseudo-channel */
13091 if (tmp->subs[SUB_REAL].dfd >= 0)
13092 {
13093 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
13094 if (res < 0) {
13095 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
13096 destroy_dahdi_pvt(tmp);
13097 return NULL;
13098 }
13099 }
13100#if 1
13101 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
13102 memset(&bi, 0, sizeof(bi));
13103 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13104 if (!res) {
13105 bi.txbufpolicy = conf->chan.buf_policy;
13106 bi.rxbufpolicy = conf->chan.buf_policy;
13107 bi.numbufs = conf->chan.buf_no;
13108 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13109 if (res < 0) {
13110 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
13111 }
13112 } else {
13113 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
13114 }
13115 tmp->buf_policy = conf->chan.buf_policy;
13116 tmp->buf_no = conf->chan.buf_no;
13117 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
13118 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
13119 tmp->faxbuf_no = conf->chan.faxbuf_no;
13120 /* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting
13121 * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
13122 * The reason the ioctl call above failed should to be determined before worrying about the
13123 * faxbuffer-related ioctl calls */
13124 tmp->bufsize = bi.bufsize;
13125 }
13126#endif
13127 tmp->immediate = conf->chan.immediate;
13128 tmp->immediatering = conf->chan.immediatering;
13129 tmp->transfertobusy = conf->chan.transfertobusy;
13130 tmp->dialmode = conf->chan.dialmode;
13131 if (chan_sig & __DAHDI_SIG_FXS) {
13132 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
13133 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
13134 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
13135 }
13136 tmp->ringt_base = ringt_base;
13137 tmp->firstradio = 0;
13138 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
13139 tmp->permcallwaiting = conf->chan.callwaiting;
13140 else
13141 tmp->permcallwaiting = 0;
13142 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
13143 tmp->destroy = 0;
13144 tmp->drings = conf->chan.drings;
13145
13146 /* 10 is a nice default. */
13147 if (tmp->drings.ringnum[0].range == 0)
13148 tmp->drings.ringnum[0].range = 10;
13149 if (tmp->drings.ringnum[1].range == 0)
13150 tmp->drings.ringnum[1].range = 10;
13151 if (tmp->drings.ringnum[2].range == 0)
13152 tmp->drings.ringnum[2].range = 10;
13153
13155 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
13156 tmp->callwaitingdeluxe = conf->chan.callwaitingdeluxe; /* Not used in DAHDI pvt, only analog pvt */
13157 tmp->threewaycalling = conf->chan.threewaycalling;
13158 tmp->threewaysilenthold = conf->chan.threewaysilenthold;
13159 tmp->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Not used in chan_dahdi.c, just analog pvt, but must exist on the DAHDI pvt anyways */
13160 tmp->adsi = conf->chan.adsi;
13161 tmp->use_smdi = conf->chan.use_smdi;
13162 tmp->permhidecallerid = conf->chan.hidecallerid;
13163 tmp->hidecalleridname = conf->chan.hidecalleridname;
13164 tmp->callreturn = conf->chan.callreturn;
13165 tmp->lastnumredial = conf->chan.lastnumredial; /* Not used in DAHDI pvt, only analog pvt */
13166 tmp->echocancel = conf->chan.echocancel;
13167 tmp->echotraining = conf->chan.echotraining;
13168 tmp->pulse = conf->chan.pulse;
13169 if (tmp->echocancel.head.tap_length) {
13170 tmp->echocanbridged = conf->chan.echocanbridged;
13171 } else {
13172 if (conf->chan.echocanbridged)
13173 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
13174 tmp->echocanbridged = 0;
13175 }
13176 tmp->busydetect = conf->chan.busydetect;
13177 tmp->busycount = conf->chan.busycount;
13178 tmp->busy_cadence = conf->chan.busy_cadence;
13179 tmp->callprogress = conf->chan.callprogress;
13180 tmp->waitfordialtone = conf->chan.waitfordialtone;
13181 tmp->dialtone_detect = conf->chan.dialtone_detect;
13182 tmp->faxdetect_timeout = conf->chan.faxdetect_timeout;
13183 tmp->firstdigit_timeout = conf->chan.firstdigit_timeout;
13184 tmp->interdigit_timeout = conf->chan.interdigit_timeout;
13185 tmp->matchdigit_timeout = conf->chan.matchdigit_timeout;
13186 tmp->cancallforward = conf->chan.cancallforward;
13187 tmp->dtmfrelax = conf->chan.dtmfrelax;
13188 tmp->callwaiting = tmp->permcallwaiting;
13189 tmp->hidecallerid = tmp->permhidecallerid;
13190 tmp->channel = channel;
13191 tmp->stripmsd = conf->chan.stripmsd;
13192 tmp->use_callerid = conf->chan.use_callerid;
13193 tmp->cid_signalling = conf->chan.cid_signalling;
13194 tmp->cid_start = conf->chan.cid_start;
13195 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
13196 tmp->restrictcid = conf->chan.restrictcid;
13197 tmp->use_callingpres = conf->chan.use_callingpres;
13198 if (tmp->usedistinctiveringdetection) {
13199 if (!tmp->use_callerid) {
13200 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
13201 tmp->use_callerid = 1;
13202 }
13203 }
13204
13205 if (tmp->cid_signalling == CID_SIG_SMDI) {
13206 if (!tmp->use_smdi) {
13207 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
13208 tmp->use_smdi = 1;
13209 }
13210 }
13211 if (tmp->use_smdi) {
13212 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
13213 if (!(tmp->smdi_iface)) {
13214 ast_log(LOG_ERROR, "Invalid SMDI port specified, disabling SMDI support\n");
13215 tmp->use_smdi = 0;
13216 }
13217 }
13218
13219 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
13220 tmp->amaflags = conf->chan.amaflags;
13221 if (!here) {
13222 tmp->confno = -1;
13223 tmp->propconfno = -1;
13224 }
13225 tmp->canpark = conf->chan.canpark;
13226 tmp->transfer = conf->chan.transfer;
13227 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
13228 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
13229 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
13230 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
13231 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
13232 ast_copy_string(tmp->description, conf->chan.description, sizeof(tmp->description));
13233 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
13234 tmp->cid_ton = 0;
13235 if (dahdi_analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
13236 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
13237 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
13238 } else {
13239 tmp->cid_num[0] = '\0';
13240 tmp->cid_name[0] = '\0';
13241 }
13242#if defined(HAVE_PRI)
13243 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
13244 tmp->cid_tag[0] = '\0';
13245 } else
13246#endif /* defined(HAVE_PRI) */
13247 {
13248 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
13249 }
13250 tmp->cid_subaddr[0] = '\0';
13251 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
13252 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
13253 /* This module does not handle MWI in an event-based manner. However, it
13254 * subscribes to MWI for each mailbox that is configured so that the core
13255 * knows that we care about it. Then, chan_dahdi will get the MWI from the
13256 * event cache instead of checking the mailbox directly. */
13258 }
13259#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13260 tmp->mwisend_setting = conf->chan.mwisend_setting;
13261 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
13262 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
13263#endif
13264
13265 tmp->group = conf->chan.group;
13266 tmp->callgroup = conf->chan.callgroup;
13267 tmp->pickupgroup= conf->chan.pickupgroup;
13269 tmp->named_callgroups = ast_ref_namedgroups(conf->chan.named_callgroups);
13271 tmp->named_pickupgroups = ast_ref_namedgroups(conf->chan.named_pickupgroups);
13272 if (conf->chan.vars) {
13273 struct ast_variable *v, *tmpvar;
13274 for (v = conf->chan.vars ; v ; v = v->next) {
13275 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
13276 if (ast_variable_list_replace(&tmp->vars, tmpvar)) {
13277 tmpvar->next = tmp->vars;
13278 tmp->vars = tmpvar;
13279 }
13280 }
13281 }
13282 }
13283 tmp->hwrxgain_enabled = conf->chan.hwrxgain_enabled;
13284 tmp->hwtxgain_enabled = conf->chan.hwtxgain_enabled;
13285 tmp->hwrxgain = conf->chan.hwrxgain;
13286 tmp->hwtxgain = conf->chan.hwtxgain;
13287 tmp->cid_rxgain = conf->chan.cid_rxgain;
13288 tmp->rxgain = conf->chan.rxgain;
13289 tmp->txgain = conf->chan.txgain;
13290 tmp->txdrc = conf->chan.txdrc;
13291 tmp->rxdrc = conf->chan.rxdrc;
13292 tmp->tonezone = conf->chan.tonezone;
13293 if (tmp->subs[SUB_REAL].dfd > -1) {
13294 if (tmp->hwrxgain_enabled) {
13295 tmp->hwrxgain_enabled = !set_hwgain(tmp->subs[SUB_REAL].dfd, tmp->hwrxgain, 0);
13296 }
13297 if (tmp->hwtxgain_enabled) {
13298 tmp->hwtxgain_enabled = !set_hwgain(tmp->subs[SUB_REAL].dfd, tmp->hwtxgain, 1);
13299 }
13300 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13301 if (tmp->dsp)
13303 dahdi_conf_update(tmp);
13304 if (!here) {
13305 switch (chan_sig) {
13307 case SIG_SS7:
13308 case SIG_MFCR2:
13309 break;
13310 default:
13311 /* Hang it up to be sure it's good */
13312 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13313 break;
13314 }
13315 }
13316 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13317 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13318 /* the dchannel is down so put the channel in alarm */
13319 switch (tmp->sig) {
13320#ifdef HAVE_PRI
13322 sig_pri_set_alarm(tmp->sig_pvt, 1);
13323 break;
13324#endif
13325#if defined(HAVE_SS7)
13326 case SIG_SS7:
13327 sig_ss7_set_alarm(tmp->sig_pvt, 1);
13328 break;
13329#endif /* defined(HAVE_SS7) */
13330 default:
13331 /* The only sig submodule left should be sig_analog. */
13332 analog_p = tmp->sig_pvt;
13333 if (analog_p) {
13334 analog_p->inalarm = 1;
13335 }
13336 tmp->inalarm = 1;
13337 break;
13338 }
13339 handle_alarms(tmp, res);
13340 }
13341 }
13342
13343 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13344 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13345 tmp->ani_info_digits = conf->chan.ani_info_digits;
13346 tmp->ani_wink_time = conf->chan.ani_wink_time;
13347 tmp->ani_timeout = conf->chan.ani_timeout;
13348 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13349 tmp->reoriginate = conf->chan.reoriginate;
13350 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13351 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13352
13353 if (!here) {
13354 tmp->locallyblocked = 0;
13355 tmp->remotelyblocked = 0;
13356 switch (tmp->sig) {
13357#if defined(HAVE_PRI)
13359 tmp->inservice = 1;/* Inservice until actually implemented. */
13360#if defined(HAVE_PRI_SERVICE_MESSAGES)
13361 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13362 if (chan_sig == SIG_PRI) {
13363 char db_chan_name[20];
13364 char db_answer[5];
13365
13366 /*
13367 * Initialize the active out-of-service status
13368 * and delete any record if the feature is not enabled.
13369 */
13370 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13371 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13372 unsigned *why;
13373
13374 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13375 if (tmp->pri->enable_service_message_support) {
13376 char state;
13377
13378 sscanf(db_answer, "%1c:%30u", &state, why);
13379
13380 /* Ensure that only the implemented bits could be set.*/
13381 *why &= (SRVST_NEAREND | SRVST_FAREND);
13382 }
13383 if (!*why) {
13384 ast_db_del(db_chan_name, SRVST_DBKEY);
13385 }
13386 }
13387 }
13388#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13389 break;
13390#endif /* defined(HAVE_PRI) */
13391#if defined(HAVE_SS7)
13392 case SIG_SS7:
13393 tmp->inservice = 0;
13394 if (tmp->ss7->flags & LINKSET_FLAG_INITIALHWBLO) {
13396 }
13397 break;
13398#endif /* defined(HAVE_SS7) */
13399 default:
13400 /* We default to in service on protocols that don't have a reset */
13401 tmp->inservice = 1;
13402 break;
13403 }
13404 }
13405
13406 switch (tmp->sig) {
13407#if defined(HAVE_PRI)
13409 if (pri_chan) {
13410 pri_chan->channel = tmp->channel;
13411 pri_chan->hidecallerid = tmp->hidecallerid;
13412 pri_chan->hidecalleridname = tmp->hidecalleridname;
13413 pri_chan->immediate = tmp->immediate;
13414 pri_chan->inalarm = tmp->inalarm;
13415 pri_chan->priexclusive = tmp->priexclusive;
13416 pri_chan->priindication_oob = tmp->priindication_oob;
13417 pri_chan->use_callerid = tmp->use_callerid;
13418 pri_chan->use_callingpres = tmp->use_callingpres;
13419 ast_copy_string(pri_chan->context, tmp->context,
13420 sizeof(pri_chan->context));
13422 sizeof(pri_chan->mohinterpret));
13423 pri_chan->stripmsd = tmp->stripmsd;
13424 }
13425 break;
13426#endif /* defined(HAVE_PRI) */
13427#if defined(HAVE_SS7)
13428 case SIG_SS7:
13429 if (ss7_chan) {
13430 ss7_chan->inalarm = tmp->inalarm;
13431 ss7_chan->inservice = tmp->inservice;
13432
13433 ss7_chan->stripmsd = tmp->stripmsd;
13434 ss7_chan->hidecallerid = tmp->hidecallerid;
13435 ss7_chan->use_callerid = tmp->use_callerid;
13436 ss7_chan->use_callingpres = tmp->use_callingpres;
13437 ss7_chan->immediate = tmp->immediate;
13438 ss7_chan->locallyblocked = tmp->locallyblocked;
13439 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13440 ast_copy_string(ss7_chan->context, tmp->context,
13441 sizeof(ss7_chan->context));
13443 sizeof(ss7_chan->mohinterpret));
13444 }
13445 break;
13446#endif /* defined(HAVE_SS7) */
13447 default:
13448 /* The only sig submodule left should be sig_analog. */
13449 analog_p = tmp->sig_pvt;
13450 if (analog_p) {
13451 analog_p->channel = tmp->channel;
13452 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13453 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13454 analog_p->ani_info_digits = conf->chan.ani_info_digits;
13455 analog_p->ani_timeout = conf->chan.ani_timeout;
13456 analog_p->ani_wink_time = conf->chan.ani_wink_time;
13457 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13458 analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13459 analog_p->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Only actually used in analog pvt, not DAHDI pvt */
13460 analog_p->callreturn = conf->chan.callreturn;
13461 analog_p->lastnumredial = conf->chan.lastnumredial; /* Only actually used in analog pvt, not DAHDI pvt */
13462 analog_p->cancallforward = conf->chan.cancallforward;
13463 analog_p->canpark = conf->chan.canpark;
13464 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13465 analog_p->immediate = conf->chan.immediate;
13466 analog_p->immediatering = conf->chan.immediatering;
13467 analog_p->permhidecallerid = conf->chan.hidecallerid; /* hidecallerid is the config setting, not permhidecallerid (~permcallwaiting above) */
13468 /* It's not necessary to set analog_p->hidecallerid here, sig_analog will set hidecallerid=permhidecaller before each call */
13469 analog_p->pulse = conf->chan.pulse;
13470 analog_p->threewaycalling = conf->chan.threewaycalling;
13471 analog_p->transfer = conf->chan.transfer;
13472 analog_p->transfertobusy = conf->chan.transfertobusy;
13473 analog_p->dialmode = conf->chan.dialmode;
13474 analog_p->use_callerid = tmp->use_callerid;
13476 analog_p->use_smdi = tmp->use_smdi;
13477 analog_p->smdi_iface = tmp->smdi_iface;
13478 analog_p->outsigmod = ANALOG_SIG_NONE;
13479 analog_p->echotraining = conf->chan.echotraining;
13480 analog_p->cid_signalling = conf->chan.cid_signalling;
13481 analog_p->stripmsd = conf->chan.stripmsd;
13482 switch (conf->chan.cid_start) {
13483 case CID_START_POLARITY:
13485 break;
13488 break;
13491 break;
13492 default:
13493 analog_p->cid_start = ANALOG_CID_START_RING;
13494 break;
13495 }
13496 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13497 analog_p->callwaitingdeluxe = conf->chan.callwaitingdeluxe;
13498 analog_p->ringt = conf->chan.ringt;
13499 analog_p->ringt_base = ringt_base;
13500 analog_p->onhooktime = time(NULL);
13501 if (chan_sig & __DAHDI_SIG_FXO) {
13502 memset(&p, 0, sizeof(p));
13503 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13504 if (!res) {
13505 analog_p->fxsoffhookstate = p.rxisoffhook;
13506 }
13507#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13508 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13509#endif
13510 }
13511 analog_p->msgstate = -1;
13512
13513 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13514 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13515 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13516
13517 analog_config_complete(analog_p);
13518 }
13519 break;
13520 }
13521#if defined(HAVE_PRI)
13522 if (tmp->channel == CHAN_PSEUDO) {
13523 /*
13524 * Save off pseudo channel buffer policy values for dynamic creation of
13525 * no B channel interfaces.
13526 */
13527 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13528 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13529 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13530 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13531 }
13532#endif /* defined(HAVE_PRI) */
13533 }
13534 if (tmp && !here) {
13535 /* Add the new channel interface to the sorted channel interface list. */
13537 }
13538 return tmp;
13539}
static char * dahdi_sig2str(int sig)
Definition: chan_dahdi.c:4721
static int sigtype_to_signalling(int sigtype)
Definition: chan_dahdi.c:12572
static int ringt_base
Configured ring timeout base.
Definition: chan_dahdi.c:881
static enum analog_sigtype dahdisig_to_analogsig(int sig)
Definition: chan_dahdi.c:1252
static int usedistinctiveringdetection
Definition: chan_dahdi.c:798
struct ast_namedgroups * ast_ref_namedgroups(struct ast_namedgroups *groups)
Definition: channel.c:7711
#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:753
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:4351
struct analog_pvt * analog_new(enum analog_sigtype signallingtype, void *private_data)
Definition: sig_analog.c:4318
@ 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:569
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:836
unsigned int immediate
Definition: sig_analog.h:298
unsigned int immediatering
Definition: sig_analog.h:299
unsigned int permcallwaiting
Definition: sig_analog.h:301
unsigned int canpark
Definition: sig_analog.h:295
unsigned int dahditrcallerid
Definition: sig_analog.h:296
int polarityonanswerdelay
Definition: sig_analog.h:326
char cid_num[AST_MAX_EXTENSION]
Definition: sig_analog.h:330
unsigned int permhidecallerid
Definition: sig_analog.h:303
unsigned int callwaitingcallerid
Definition: sig_analog.h:311
unsigned int ani_wink_time
Definition: sig_analog.h:289
enum analog_sigtype outsigmod
Definition: sig_analog.h:322
unsigned int usedistinctiveringdetection
Definition: sig_analog.h:310
unsigned int answeronpolarityswitch
Definition: sig_analog.h:291
unsigned int threewaycalling
Definition: sig_analog.h:305
unsigned int pulse
Definition: sig_analog.h:304
int echotraining
Definition: sig_analog.h:324
unsigned int hanguponpolarityswitch
Definition: sig_analog.h:297
unsigned int callwaitingdeluxe
Definition: sig_analog.h:302
enum analog_cid_start cid_start
Definition: sig_analog.h:328
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:315
unsigned int ani_timeout
Definition: sig_analog.h:288
unsigned int lastnumredial
Definition: sig_analog.h:300
int ringt_base
Definition: sig_analog.h:385
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:325
unsigned int transfer
Definition: sig_analog.h:307
unsigned int transfertobusy
Definition: sig_analog.h:308
unsigned int inalarm
Definition: sig_analog.h:343
char cid_name[AST_MAX_EXTENSION]
Definition: sig_analog.h:331
int stripmsd
Definition: sig_analog.h:327
unsigned int calledsubscriberheld
Definition: sig_analog.h:292
char mohsuggest[MAX_MUSICCLASS]
Definition: sig_analog.h:329
unsigned int use_callerid
Definition: sig_analog.h:309
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
Definition: sig_analog.h:317
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:377
int sendcalleridafter
Send caller ID on FXS after this many rings. Set to 1 for US.
Definition: chan_dahdi.h:740
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:433
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:401
unsigned int priexclusive
TRUE if PRI B channels are always exclusively selected.
Definition: chan_dahdi.h:353
int tonezone
Definition: chan_dahdi.h:167
unsigned int callwaitingdeluxe
TRUE if Call Waiting Deluxe options should be available.
Definition: chan_dahdi.h:338
unsigned int ani_timeout
INTEGER, length of ANI failure timeout in ms.
Definition: chan_dahdi.h:195
unsigned int lastnumredial
TRUE if last number redial enabled.
Definition: chan_dahdi.h:448
unsigned int restrictcid
TRUE if caller ID is restricted.
Definition: chan_dahdi.h:367
unsigned int priindication_oob
TRUE if PRI congestion/busy indications are sent out-of-band.
Definition: chan_dahdi.h:348
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 calledsubscriberheld
TRUE if Called Subscriber held is enabled. This allows a single incoming call to hold a DAHDI channel...
Definition: chan_dahdi.h:213
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 dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, ANALOG_CID_START_DTMF_NOALERT, ANALOG_CID_START_POLARITY, ANALOG_CID_START_POLARITY_IN, ANALOG_CID_START_RING, analog_config_complete(), analog_new(), ANALOG_SIG_NONE, dahdi_pvt::ani_info_digits, analog_pvt::ani_info_digits, dahdi_pvt::ani_timeout, analog_pvt::ani_timeout, dahdi_pvt::ani_wink_time, analog_pvt::ani_wink_time, dahdi_pvt::answeronpolarityswitch, 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(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufsize, dahdi_pvt::busy_cadence, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::calledsubscriberheld, analog_pvt::calledsubscriberheld, dahdi_pvt::callgroup, dahdi_pvt::callprogress, dahdi_pvt::callreturn, analog_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, analog_pvt::callwaitingcallerid, dahdi_pvt::callwaitingdeluxe, analog_pvt::callwaitingdeluxe, dahdi_pvt::cancallforward, analog_pvt::cancallforward, dahdi_pvt::canpark, analog_pvt::canpark, dahdi_pvt::cc_params, CHAN_PSEUDO, dahdi_pvt::channel, analog_pvt::channel, sig_pri_chan::channel, sig_ss7_chan::channel, sig_ss7_chan::cic, dahdi_pvt::cid_name, analog_pvt::cid_name, dahdi_pvt::cid_num, analog_pvt::cid_num, dahdi_pvt::cid_rxgain, CID_SIG_SMDI, dahdi_pvt::cid_signalling, analog_pvt::cid_signalling, dahdi_pvt::cid_start, analog_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_tag, dahdi_pvt::cid_ton, dahdi_pvt::confno, dahdi_pvt::context, 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(), dahdi_pvt::dahditrcallerid, analog_pvt::dahditrcallerid, dahdi_pvt::defcontext, dahdi_pvt::description, dahdi_pvt::destroy, destroy_dahdi_pvt(), dahdi_subchannel::dfd, dahdi_pvt::dialmode, analog_pvt::dialmode, sig_pri_span::dialplan, dahdi_pvt::dialtone_detect, sig_ss7_chan::dpc, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, analog_pvt::echotraining, errno, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxdetect_timeout, ast_variable::file, dahdi_pvt::firstdigit_timeout, dahdi_pvt::firstradio, analog_pvt::fxsoffhookstate, get_alarms(), dahdi_pvt::group, handle_alarms(), dahdi_pvt::hanguponpolarityswitch, analog_pvt::hanguponpolarityswitch, dahdi_pvt::head, dahdi_pvt::hidecallerid, sig_pri_chan::hidecallerid, sig_ss7_chan::hidecallerid, dahdi_pvt::hidecalleridname, sig_pri_chan::hidecalleridname, dahdi_pvt::hwrxgain, dahdi_pvt::hwrxgain_enabled, dahdi_pvt::hwtxgain, dahdi_pvt::hwtxgain_enabled, sig_pri_span::idledial, sig_pri_span::idleext, ifcount, iflist, dahdi_pvt::immediate, analog_pvt::immediate, sig_pri_chan::immediate, sig_ss7_chan::immediate, dahdi_pvt::immediatering, analog_pvt::immediatering, dahdi_pvt::inalarm, analog_pvt::inalarm, sig_pri_chan::inalarm, sig_ss7_chan::inalarm, dahdi_pvt::inservice, sig_ss7_chan::inservice, dahdi_pvt::interdigit_timeout, dahdi_pvt::language, dahdi_pvt::lastnumredial, analog_pvt::lastnumredial, dahdi_pvt::law, dahdi_pvt::law_default, LINKSET_FLAG_INITIALHWBLO, dahdi_pvt::locallyblocked, sig_ss7_chan::locallyblocked, dahdi_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::matchdigit_timeout, sig_pri_span::minidle, sig_pri_span::minunused, dahdi_pvt::mohinterpret, sig_pri_chan::mohinterpret, sig_ss7_chan::mohinterpret, dahdi_pvt::mohsuggest, analog_pvt::mohsuggest, analog_pvt::msgstate, dahdi_pvt::mwi_event_sub, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, ast_variable::name, dahdi_pvt::named_callgroups, dahdi_pvt::named_pickupgroups, dahdi_pvt::next, ast_variable::next, sig_pri_span::nodetype, NULL, NUM_SPANS, sig_pri_span::numchans, analog_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_pvt::outsigmod, analog_pvt::outsigmod, dahdi_pvt::parkinglot, dahdi_pvt::permcallwaiting, analog_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, analog_pvt::permhidecallerid, dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, analog_pvt::polarityonanswerdelay, dahdi_pvt::priexclusive, sig_pri_chan::priexclusive, dahdi_pvt::priindication_oob, sig_pri_chan::priindication_oob, dahdi_pvt::propconfno, dahdi_pvt::pulse, analog_pvt::pulse, sig_pri_span::pvts, dahdi_pvt::radio, distRingData::range, dahdi_pvt::remotelyblocked, sig_ss7_chan::remotelyblocked, dahdi_pvt::reoriginate, dahdi_pvt::restrictcid, dahdi_distRings::ringnum, analog_pvt::ringt, ringt_base, dahdi_pvt::ringt_base, analog_pvt::ringt_base, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, set_actual_gain(), set_hwgain(), dahdi_pvt::sig, sig2str, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, sig_pri_chan_new(), SIG_PRI_LIB_HANDLE_CASES, SIG_PRI_NUM_DCHANS, sig_pri_set_alarm(), dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sig_ss7_chan_new(), sig_ss7_set_alarm(), sigtype_to_signalling(), dahdi_pvt::smdi_iface, analog_pvt::smdi_iface, dahdi_pvt::span, SS7_BLOCKED_HARDWARE, stasis_subscription_cb_noop(), state, dahdi_pvt::stripmsd, analog_pvt::stripmsd, sig_pri_chan::stripmsd, sig_ss7_chan::stripmsd, SUB_REAL, dahdi_pvt::subs, sig_pri_span::switchtype, dahdi_pvt::threewaycalling, analog_pvt::threewaycalling, dahdi_pvt::threewaysilenthold, dahdi_pvt::tonezone, dahdi_pvt::transfer, analog_pvt::transfer, dahdi_pvt::transfertobusy, analog_pvt::transfertobusy, sig_pri_span::trunkgroup, dahdi_pvt::txdrc, dahdi_pvt::txgain, dahdi_pvt::use_callerid, analog_pvt::use_callerid, sig_pri_chan::use_callerid, sig_ss7_chan::use_callerid, dahdi_pvt::use_callingpres, sig_pri_chan::use_callingpres, sig_ss7_chan::use_callingpres, dahdi_pvt::use_smdi, analog_pvt::use_smdi, usedistinctiveringdetection, dahdi_pvt::usedistinctiveringdetection, analog_pvt::usedistinctiveringdetection, dahdi_pvt::usefaxbuffers, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

Referenced by build_channels(), and process_dahdi().

◆ monitor_pfds_clean()

static void monitor_pfds_clean ( void *  arg)
static

Definition at line 11947 of file chan_dahdi.c.

11947 {
11948 struct pollfd **pfds = arg;
11949 ast_free(*pfds);
11950}

References ast_free.

Referenced by do_monitor().

◆ mwi_send_init()

static int mwi_send_init ( struct dahdi_pvt pvt)
static

Definition at line 11353 of file chan_dahdi.c.

11354{
11355 int x;
11356
11357#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11358 /* Determine how this spill is to be sent */
11359 if (pvt->mwisend_rpas) {
11361 pvt->mwisendactive = 1;
11362 } else if (pvt->mwisend_fsk) {
11364 pvt->mwisendactive = 1;
11365 } else {
11366 pvt->mwisendactive = 0;
11367 return 0;
11368 }
11369#else
11370 if (mwisend_rpas) {
11372 } else {
11374 }
11375 pvt->mwisendactive = 1;
11376#endif
11377
11378 if (pvt->cidspill) {
11379 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11380 ast_free(pvt->cidspill);
11381 pvt->cidspill = NULL;
11382 pvt->cidpos = 0;
11383 pvt->cidlen = 0;
11384 }
11386 if (!pvt->cidspill) {
11387 pvt->mwisendactive = 0;
11388 return -1;
11389 }
11390 x = DAHDI_FLUSH_BOTH;
11391 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11392 x = 3000;
11393 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11394#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11395 if (pvt->mwisend_fsk) {
11396#endif
11398 CID_MWI_TYPE_MDMF_FULL, AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11399 pvt->cidpos = 0;
11400#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11401 }
11402#endif
11403 return 0;
11404}
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:952
#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:793
@ 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:486
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 11406 of file chan_dahdi.c.

11407{
11408 struct timeval now;
11409 int res;
11410
11411 /* sanity check to catch if this had been interrupted previously
11412 * i.e. state says there is more to do but there is no spill allocated
11413 */
11414 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11416 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11417 /* Normal processing -- Perform mwi send action */
11418 switch ( pvt->mwisend_data.mwisend_current) {
11419 case MWI_SEND_SA:
11420 /* Send the Ring Pulse Signal Alert */
11421 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11422 if (res) {
11423 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11424 goto quit;
11425 }
11426 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11428 break;
11429 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */
11430 break;
11431 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/
11432#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11433 if (pvt->mwisend_fsk) {
11434#endif
11435 gettimeofday(&now, NULL);
11436 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11438 }
11439#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11440 } else { /* support for mwisendtype=nofsk */
11442 }
11443#endif
11444 break;
11445 case MWI_SEND_SPILL:
11446 /* We read some number of bytes. Write an equal amount of data */
11447 if (0 < num_read) {
11448 if (num_read > pvt->cidlen - pvt->cidpos) {
11449 num_read = pvt->cidlen - pvt->cidpos;
11450 }
11451 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11452 if (res > 0) {
11453 pvt->cidpos += res;
11454 if (pvt->cidpos >= pvt->cidlen) {
11456 }
11457 } else {
11458 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11459 goto quit;
11460 }
11461 }
11462 break;
11463 case MWI_SEND_CLEANUP:
11464 /* For now, do nothing */
11466 break;
11467 default:
11468 /* Should not get here, punt*/
11469 goto quit;
11470 }
11471 }
11472
11474 if (pvt->cidspill) {
11475 ast_free(pvt->cidspill);
11476 pvt->cidspill = NULL;
11477 pvt->cidpos = 0;
11478 pvt->cidlen = 0;
11479 }
11480 pvt->mwisendactive = 0;
11481 }
11482 return 0;
11483quit:
11484 if (pvt->cidspill) {
11485 ast_free(pvt->cidspill);
11486 pvt->cidspill = NULL;
11487 pvt->cidpos = 0;
11488 pvt->cidlen = 0;
11489 }
11490 pvt->mwisendactive = 0;
11491 return -1;
11492}
static struct dahdi_ring_cadence AS_RP_cadence
Definition: chan_dahdi.c:779
@ 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 11494 of file chan_dahdi.c.

11495{
11496 int handled = 0;
11497
11499 switch (event) {
11500 case DAHDI_EVENT_RINGEROFF:
11502 handled = 1;
11503
11504 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11505 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11506 ast_free(pvt->cidspill);
11507 pvt->cidspill = NULL;
11509 pvt->mwisendactive = 0;
11510 } else {
11512 gettimeofday(&pvt->mwisend_data.pause, NULL);
11513 }
11514 }
11515 break;
11516 /* Going off hook, I need to punt this spill */
11517 case DAHDI_EVENT_RINGOFFHOOK:
11518 if (pvt->cidspill) {
11519 ast_free(pvt->cidspill);
11520 pvt->cidspill = NULL;
11521 pvt->cidpos = 0;
11522 pvt->cidlen = 0;
11523 }
11525 pvt->mwisendactive = 0;
11526 break;
11527 case DAHDI_EVENT_RINGERON:
11528 case DAHDI_EVENT_HOOKCOMPLETE:
11529 break;
11530 default:
11531 break;
11532 }
11533 }
11534 return handled;
11535}

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

11197{
11198 struct mwi_thread_data *mtd = data;
11199 struct callerid_state *cs;
11200 pthread_t threadid;
11201 int samples = 0;
11202 char *name, *number;
11203 int flags;
11204 int i, res;
11205 unsigned int spill_done = 0;
11206 int spill_result = -1;
11207
11208 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11209 goto quit_no_clean;
11210 }
11211
11212 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11213
11214 bump_gains(mtd->pvt);
11215
11216 for (;;) {
11217 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11218 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11219 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11220 goto quit;
11221 }
11222
11223 if (i & DAHDI_IOMUX_SIGEVENT) {
11224 struct ast_channel *chan;
11225 ast_callid callid = 0;
11226 int callid_created;
11227
11228 /* If we get an event, screen out events that we do not act on.
11229 * Otherwise, cancel and go to the simple switch to let it deal with it.
11230 */
11231 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11232
11233 switch (res) {
11234 case DAHDI_EVENT_NEONMWI_ACTIVE:
11235 case DAHDI_EVENT_NEONMWI_INACTIVE:
11236 case DAHDI_EVENT_NONE:
11237 case DAHDI_EVENT_BITSCHANGED:
11238 break;
11239 case DAHDI_EVENT_NOALARM:
11240 if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11241 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11242
11243 analog_p->inalarm = 0;
11244 }
11245 mtd->pvt->inalarm = 0;
11247 break;
11248 case DAHDI_EVENT_ALARM:
11249 if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11250 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11251
11252 analog_p->inalarm = 1;
11253 }
11254 mtd->pvt->inalarm = 1;
11255 res = get_alarms(mtd->pvt);
11256 handle_alarms(mtd->pvt, res);
11257 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11258 default:
11259 callid_created = ast_callid_threadstorage_auto(&callid);
11260 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11261 callerid_free(cs);
11262
11263 restore_gains(mtd->pvt);
11264 mtd->pvt->ringt = mtd->pvt->ringt_base;
11265
11266 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, callid))) {
11267 int result;
11268
11269 if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11271 } else {
11273 }
11274 if (result) {
11275 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11276 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11277 if (res < 0)
11278 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11279 ast_hangup(chan);
11280 }
11281 } else {
11282 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11283 }
11284
11285 ast_callid_threadstorage_auto_clean(callid, callid_created);
11286 goto quit_no_clean;
11287 }
11288 } else if (i & DAHDI_IOMUX_READ) {
11289 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11290 if (errno != ELAST) {
11291 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11292 goto quit;
11293 }
11294 break;
11295 }
11296 samples += res;
11297 if (!spill_done) {
11298 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11299 /*
11300 * The previous diagnostic message output likely
11301 * explains why it failed.
11302 */
11303 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11304 break;
11305 } else if (spill_result) {
11306 spill_done = 1;
11307 }
11308 } else {
11309 /* keep reading data until the energy level drops below the threshold
11310 so we don't get another 'trigger' on the remaining carrier signal
11311 */
11312 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11313 break;
11314 }
11315 if (samples > (8000 * 4)) /*Termination case - time to give up*/
11316 break;
11317 }
11318 }
11319
11320 if (spill_result == 1) {
11321 callerid_get(cs, &name, &number, &flags);
11322 if (flags & CID_MSGWAITING) {
11323 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11324 notify_message(mtd->pvt->mailbox, 1);
11325 } else if (flags & CID_NOMSGWAITING) {
11326 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11327 notify_message(mtd->pvt->mailbox, 0);
11328 } else {
11329 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11330 }
11331 }
11332
11333
11334quit:
11335 callerid_free(cs);
11336
11337 restore_gains(mtd->pvt);
11338
11339quit_no_clean:
11340 mtd->pvt->mwimonitoractive = 0;
11341 ast_free(mtd);
11342
11343 return NULL;
11344}
#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:2977
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 2333 of file chan_dahdi.c.

2334{
2335 struct dahdi_pvt *p = pvt;
2336 int res, law;
2337
2338 p->faxhandled = 0;
2339 p->didtdd = 0;
2340
2341 if (p->dsp) {
2342 ast_dsp_free(p->dsp);
2343 p->dsp = NULL;
2344 }
2345
2346 p->law = p->law_default;
2347 law = p->law_default;
2348 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2349 if (res < 0)
2350 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2351
2353
2354#if 1
2355 {
2356 int i;
2357 p->owner = NULL;
2358 /* Cleanup owners here */
2359 for (i = 0; i < 3; i++) {
2360 p->subs[i].owner = NULL;
2361 }
2362 }
2363#endif
2364
2365 reset_conf(p);
2366 if (num_restart_pending == 0) {
2368 }
2369}

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

2651{
2652 struct dahdi_pvt *p = pvt;
2653
2654 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
2655}
static int analogsub_to_dahdisub(enum analog_sub analogsub)
Definition: chan_dahdi.c:1323

References alloc_sub(), and analogsub_to_dahdisub().

◆ my_answer_polarityswitch()

static void my_answer_polarityswitch ( void *  pvt)
static

Definition at line 2885 of file chan_dahdi.c.

2886{
2887 struct dahdi_pvt *p = pvt;
2888
2889 if (!p->answeronpolarityswitch) {
2890 return;
2891 }
2892
2893 my_set_polarity(pvt, 1);
2894}
static void my_set_polarity(void *pvt, int value)
Definition: chan_dahdi.c:2865

References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().

◆ my_callwait()

static int my_callwait ( void *  pvt)
static

Definition at line 1734 of file chan_dahdi.c.

1735{
1736 struct dahdi_pvt *p = pvt;
1737
1739 if (p->cidspill) {
1740 ast_log(LOG_WARNING, "Spill already exists?!?\n");
1741 ast_free(p->cidspill);
1742 }
1743
1744 /*
1745 * SAS: Subscriber Alert Signal, 440Hz for 300ms
1746 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
1747 */
1748 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1749 return -1;
1750 save_conference(p);
1751 /* Silence */
1752 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1753 if (!p->callwaitrings && p->callwaitingcallerid) {
1754 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1755 p->callwaitcas = 1;
1756 p->cidlen = 2400 + 680 + READ_SIZE * 4;
1757 } else {
1758 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1759 p->callwaitcas = 0;
1760 p->cidlen = 2400 + READ_SIZE * 4;
1761 }
1762 p->cidpos = 0;
1763 send_callerid(p);
1764
1765 return 0;
1766}

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

2284{
2285 struct dahdi_pvt *p = pvt;
2286
2287 ast_free(p->cidspill);
2288 p->cidspill = NULL;
2290}

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

◆ my_check_confirmanswer()

static int my_check_confirmanswer ( void *  pvt)
static

Definition at line 2266 of file chan_dahdi.c.

2267{
2268 struct dahdi_pvt *p = pvt;
2269 if (p->confirmanswer) {
2270 return 1;
2271 }
2272
2273 return 0;
2274}

References dahdi_pvt::confirmanswer.

◆ my_check_for_conference()

static int my_check_for_conference ( void *  pvt)
static

Definition at line 2443 of file chan_dahdi.c.

2444{
2445 struct dahdi_pvt *p = pvt;
2446 return check_for_conference(p);
2447}

References check_for_conference().

◆ my_check_waitingfordt()

static int my_check_waitingfordt ( void *  pvt)
static

Definition at line 2249 of file chan_dahdi.c.

2250{
2251 struct dahdi_pvt *p = pvt;
2252
2253 if (p->waitingfordt.tv_sec) {
2254 return 1;
2255 }
2256
2257 return 0;
2258}

References dahdi_pvt::waitingfordt.

◆ my_complete_conference_update()

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

Definition at line 2393 of file chan_dahdi.c.

2394{
2395 struct dahdi_pvt *p = pvt;
2396 int needconf = needconference;
2397 int x;
2398 int useslavenative;
2399 struct dahdi_pvt *slave = NULL;
2400
2401 useslavenative = isslavenative(p, &slave);
2402
2403 /* If we have a slave, add him to our conference now. or DAX
2404 if this is slave native */
2405 for (x = 0; x < MAX_SLAVES; x++) {
2406 if (p->slaves[x]) {
2407 if (useslavenative)
2408 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
2409 else {
2410 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
2411 needconf++;
2412 }
2413 }
2414 }
2415 /* If we're supposed to be in there, do so now */
2416 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
2417 if (useslavenative)
2418 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
2419 else {
2420 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
2421 needconf++;
2422 }
2423 }
2424 /* If we have a master, add ourselves to his conference */
2425 if (p->master) {
2426 if (isslavenative(p->master, NULL)) {
2428 } else {
2429 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
2430 }
2431 }
2432 if (!needconf) {
2433 /* Nobody is left (or should be left) in our conference.
2434 Kill it. */
2435 p->confno = -1;
2436 }
2437
2438 return 0;
2439}

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

2384{
2385 struct dahdi_pvt *p = pvt;
2386 int x = analogsub_to_dahdisub(sub);
2387
2388 return conf_add(p, &p->subs[x], x, 0);
2389}
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 2373 of file chan_dahdi.c.

2374{
2375 struct dahdi_pvt *p = pvt;
2376 int x = analogsub_to_dahdisub(sub);
2377
2378 return conf_del(p, &p->subs[x], x);
2379}

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

2293{
2294 struct dahdi_pvt *p = pvt;
2295 return dahdi_confmute(p, mute);
2296}

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

9320{
9321 int sent=0;
9322 int size;
9323 int res;
9324 int fd;
9325 fd = p->subs[idx].dfd;
9326 while (len) {
9327 size = len;
9328 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
9329 size = (linear ? READ_SIZE * 2 : READ_SIZE);
9330 res = write(fd, buf, size);
9331 if (res != size) {
9332 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
9333 return sent;
9334 }
9335 len -= size;
9336 buf += size;
9337 }
9338 return sent;
9339}

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

1974{
1975 struct dahdi_pvt *p = pvt;
1976
1978}

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

3000{
3001 struct dahdi_pvt *p = pvt;
3002
3003 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
3004 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
3005 return -1;
3006 }
3007
3008 if (sub != ANALOG_SUB_REAL) {
3009 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
3010 dop->dialstr, p->channel, sub);
3011 return -1;
3012 }
3013
3014 return dahdi_dial_str(p, DAHDI_DIAL_OP_REPLACE, dop->dialstr);
3015}
@ 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 1596 of file chan_dahdi.c.

1597{
1598 unsigned char buf[256];
1599 int distMatches;
1600 int curRingData[RING_PATTERNS];
1601 int receivedRingT;
1602 int counter1;
1603 int counter;
1604 int i;
1605 int res;
1606 int checkaftercid = 0;
1607 const char *matched_context;
1608 struct dahdi_pvt *p = pvt;
1609 struct analog_pvt *analog_p = p->sig_pvt;
1610
1611 if (ringdata == NULL) {
1612 ringdata = curRingData;
1613 } else {
1614 checkaftercid = 1;
1615 }
1616
1617 /* We must have a ring by now so lets try to listen for distinctive ringing */
1618 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
1619 /* Clear the current ring data array so we don't have old data in it. */
1620 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
1621 ringdata[receivedRingT] = 0;
1622 receivedRingT = 0;
1623
1624 if (checkaftercid && distinctiveringaftercid) {
1625 ast_verb(3, "Detecting post-CID distinctive ring\n");
1626 }
1627
1628 for (;;) {
1629 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
1630 res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i);
1631 if (res) {
1632 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
1633 ast_hangup(chan);
1634 return 1;
1635 }
1636 if (i & DAHDI_IOMUX_SIGEVENT) {
1637 res = dahdi_get_event(p->subs[idx].dfd);
1638 ast_debug(3, "Got event %d (%s)...\n", res, event2str(res));
1639 if (res == DAHDI_EVENT_NOALARM) {
1640 p->inalarm = 0;
1641 analog_p->inalarm = 0;
1642 } else if (res == DAHDI_EVENT_RINGOFFHOOK) {
1643 /* Let us detect distinctive ring */
1644 ringdata[receivedRingT] = analog_p->ringt;
1645
1646 if (analog_p->ringt < analog_p->ringt_base / 2) {
1647 break;
1648 }
1649 /* Increment the ringT counter so we can match it against
1650 values in chan_dahdi.conf for distinctive ring */
1651 if (++receivedRingT == RING_PATTERNS) {
1652 break;
1653 }
1654 }
1655 } else if (i & DAHDI_IOMUX_READ) {
1656 res = read(p->subs[idx].dfd, buf, sizeof(buf));
1657 if (res < 0) {
1658 if (errno != ELAST) {
1659 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1660 ast_hangup(chan);
1661 return 1;
1662 }
1663 break;
1664 }
1665 if (analog_p->ringt > 0) {
1666 if (!(--analog_p->ringt)) {
1667 break;
1668 }
1669 }
1670 }
1671 }
1672 }
1673
1674 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
1675 ast_verb(3, "Detected ring pattern: %d,%d,%d\n", ringdata[0], ringdata[1], ringdata[2]);
1676 matched_context = p->defcontext;
1677 for (counter = 0; counter < 3; counter++) {
1678 int range = p->drings.ringnum[counter].range;
1679
1680 distMatches = 0;
1681 ast_verb(3, "Checking %d,%d,%d with +/- %d range\n",
1682 p->drings.ringnum[counter].ring[0],
1683 p->drings.ringnum[counter].ring[1],
1684 p->drings.ringnum[counter].ring[2],
1685 range);
1686 for (counter1 = 0; counter1 < 3; counter1++) {
1687 int ring = p->drings.ringnum[counter].ring[counter1];
1688
1689 if (ring == -1) {
1690 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
1691 ringdata[counter1]);
1692 distMatches++;
1693 } else if (ring - range <= ringdata[counter1] && ringdata[counter1] <= ring + range) {
1694 ast_verb(3, "Ring pattern %d is in range: %d to %d\n",
1695 ringdata[counter1], ring - range, ring + range);
1696 distMatches++;
1697 } else {
1698 /* The current dring pattern cannot match. */
1699 break;
1700 }
1701 }
1702
1703 if (distMatches == 3) {
1704 /* The ring matches, set the context to whatever is for distinctive ring.. */
1705 matched_context = S_OR(p->drings.ringContext[counter].contextData, p->defcontext);
1706 ast_verb(3, "Matched Distinctive Ring context %s\n", matched_context);
1707 break;
1708 }
1709 }
1710
1711 /* Set selected distinctive ring context if not already set. */
1712 if (strcmp(p->context, matched_context) != 0) {
1713 ast_copy_string(p->context, matched_context, sizeof(p->context));
1714 ast_channel_context_set(chan, matched_context);
1715 }
1716
1717 return 0;
1718}
#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 1821 of file chan_dahdi.c.

1822{
1823 struct dahdi_pvt *p = pvt;
1824 if (p->dsp)
1826
1827 return 0;
1828}

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

1831{
1832 struct dahdi_pvt *p = pvt;
1833
1834 if (p->channel == CHAN_PSEUDO)
1835 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
1836
1837 if (mode == ANALOG_DIGITMODE_DTMF) {
1838 /* If we do hardware dtmf, no need for a DSP */
1839 if (p->hardwaredtmf) {
1840 if (p->dsp) {
1841 ast_dsp_free(p->dsp);
1842 p->dsp = NULL;
1843 }
1844 return 0;
1845 }
1846
1847 if (!p->dsp) {
1848 p->dsp = ast_dsp_new();
1849 if (!p->dsp) {
1850 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1851 return -1;
1852 }
1853 }
1854
1856 } else if (mode == ANALOG_DIGITMODE_MF) {
1857 if (!p->dsp) {
1858 p->dsp = ast_dsp_new();
1859 if (!p->dsp) {
1860 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1861 return -1;
1862 }
1863 }
1865 }
1866 return 0;
1867}
@ 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 2844 of file chan_dahdi.c.

2845{
2846 struct dahdi_pvt *p = pvt;
2847 int func = DAHDI_FLASH;
2848 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
2849}

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

2098{
2099 int res;
2100 struct dahdi_pvt *p = pvt;
2101
2102 res = get_alarms(p);
2103 handle_alarms(p, res);
2104}

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

1500{
1501 struct dahdi_pvt *p = pvt;
1502 struct analog_pvt *analog_p = p->sig_pvt;
1503 struct pollfd poller;
1504 char *name, *num;
1505 int index = SUB_REAL;
1506 int res;
1507 unsigned char buf[256];
1508 int flags;
1509 int redirecting;
1510
1511 poller.fd = p->subs[SUB_REAL].dfd;
1512 poller.events = POLLPRI | POLLIN;
1513 poller.revents = 0;
1514
1515 res = poll(&poller, 1, timeout);
1516
1517 if (poller.revents & POLLPRI) {
1519 return 1;
1520 }
1521
1522 if (poller.revents & POLLIN) {
1523 /*** NOTES ***/
1524 /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
1525 * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
1526 * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
1527 * a failure and die, and returning 2 means no event was received. */
1528 res = read(p->subs[index].dfd, buf, sizeof(buf));
1529 if (res < 0) {
1530 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1531 return -1;
1532 }
1533
1534 if (analog_p->ringt > 0) {
1535 if (!(--analog_p->ringt)) {
1536 /* only return if we timeout from a ring event */
1537 return -1;
1538 }
1539 }
1540
1541 if (p->cid_signalling == CID_SIG_V23_JP) {
1542 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
1543 } else {
1544 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
1545 }
1546 if (res < 0) {
1547 /*
1548 * The previous diagnostic message output likely
1549 * explains why it failed.
1550 */
1551 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
1552 return -1;
1553 }
1554
1555 if (res == 1) {
1556 struct ast_channel *chan = analog_p->ss_astchan;
1558 if (name)
1560 if (num)
1561 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
1562
1564 /* If we got a presentation, we must set it on the channel */
1565 struct ast_party_caller caller;
1566
1568 caller.id.name.presentation = caller.id.number.presentation = (flags & CID_PRIVATE_NUMBER) ?
1571 ast_party_caller_free(&caller);
1572 }
1573 if (redirecting) {
1574 /* There is a redirecting reason available in the Caller*ID received.
1575 * No idea what the redirecting number is, since the Caller*ID protocol
1576 * has no parameter for that, but at least we know WHY it was redirected. */
1577 ast_channel_redirecting(chan)->reason.code = redirecting;
1578 }
1579
1580 if (flags & CID_QUALIFIER) {
1581 /* This is the inverse of how the qualifier is set in sig_analog */
1582 pbx_builtin_setvar_helper(chan, "CALL_QUALIFIER", "1");
1583 }
1584
1585 ast_debug(1, "CallerID number: %s, name: %s, flags=%d, redirecting=%s\n", num, name, flags, ast_redirecting_reason_name(&ast_channel_redirecting(chan)->reason));
1586 return 0;
1587 }
1588 }
1589
1590 *ev = ANALOG_EVENT_NONE;
1591 return 2;
1592}
#define CID_UNKNOWN_NUMBER
Definition: callerid.h:55
#define AST_PRES_USER_NUMBER_UNSCREENED
Definition: callerid.h:426
#define AST_PRES_UNAVAILABLE
Definition: callerid.h:434
#define AST_PRES_RESTRICTED
Definition: callerid.h:433
void callerid_get_with_redirecting(struct callerid_state *cid, char **name, char **number, int *flags, int *redirecting)
Extract info out of callerID state machine. Flags are listed above.
Definition: callerid.c:189
const char * ast_redirecting_reason_name(const struct ast_party_redirecting_reason *data)
Convert redirecting reason value to text code.
Definition: callerid.c:1449
#define CID_PRIVATE_NUMBER
Definition: callerid.h:53
#define CID_QUALIFIER
Definition: callerid.h:58
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:1974
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:1966
void ast_party_caller_free(struct ast_party_caller *doomed)
Destroy the caller party contents.
Definition: channel.c:1982
#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:381
struct ast_party_redirecting redirecting
Redirecting/Diversion information.
struct ast_flags flags
Caller Party information.
Definition: channel.h:420
int code
enum AST_REDIRECTING_REASON value for redirection
Definition: channel.h:512
struct ast_party_redirecting_reason reason
Reason for the redirection.
Definition: channel.h:544
struct callerid_state * cs
Definition: chan_dahdi.h:126

References ANALOG_EVENT_NONE, ANALOG_MAX_CID, ast_channel_caller(), ast_channel_redirecting(), 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, ast_redirecting_reason_name(), buf, callerid_feed(), callerid_feed_jp(), callerid_get_with_redirecting(), CID_PRIVATE_NUMBER, CID_QUALIFIER, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, CID_UNKNOWN_NUMBER, ast_party_redirecting_reason::code, dahdi_pvt::cs, dahdi_get_event(), dahdievent_to_analogevent(), dahdi_subchannel::dfd, errno, ast_channel::flags, ast_party_caller::id, LOG_WARNING, name, ast_party_id::name, NULL, ast_party_id::number, pbx_builtin_setvar_helper(), ast_party_name::presentation, ast_party_number::presentation, ast_party_redirecting::reason, ast_channel::redirecting, 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 2780 of file chan_dahdi.c.

2781{
2782 struct dahdi_pvt *p = pvt;
2783 int res;
2784
2785 if (p->fake_event) {
2786 res = p->fake_event;
2787 p->fake_event = 0;
2788 } else
2789 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
2790
2791 return dahdievent_to_analogevent(res);
2792}

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

2312{
2313 struct dahdi_pvt *p = pvt;
2314
2315 return p->dialstring;
2316}

References dahdi_pvt::dialstring.

◆ my_get_sigpvt_bridged_channel()

static void * my_get_sigpvt_bridged_channel ( struct ast_channel chan)
static

Definition at line 2106 of file chan_dahdi.c.

2107{
2109
2110 if (bridged && ast_channel_tech(bridged) == &dahdi_tech) {
2111 struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
2112
2113 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
2114 return p->sig_pvt;
2115 }
2116 }
2117 return NULL;
2118}

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

2121{
2122 struct dahdi_pvt *p = pvt;
2123 int dahdi_sub = analogsub_to_dahdisub(sub);
2124 return p->subs[dahdi_sub].dfd;
2125}

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

9871{
9872 char c;
9873
9874 *str = 0; /* start with empty output buffer */
9875 for (;;)
9876 {
9877 /* Wait for the first digit (up to specified ms). */
9878 c = ast_waitfordigit(chan, ms);
9879 /* if timeout, hangup or error, return as such */
9880 if (c < 1)
9881 return c;
9882 *str++ = c;
9883 *str = 0;
9884 if (strchr(term, c))
9885 return 1;
9886 }
9887}
const char * str
Definition: app_jack.c:150

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

1888{
1889 struct ast_frame *f = *dest;
1890 struct dahdi_pvt *p = pvt;
1891 int idx = analogsub_to_dahdisub(analog_index);
1892
1893 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
1894 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
1895 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
1896
1897 if (f->subclass.integer == 'f') {
1898 if (f->frametype == AST_FRAME_DTMF_END) {
1899 /* Fax tone -- Handle and return NULL */
1900 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
1901 /* If faxbuffers are configured, use them for the fax transmission */
1902 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
1903 struct dahdi_bufferinfo bi = {
1904 .txbufpolicy = p->faxbuf_policy,
1905 .bufsize = p->bufsize,
1906 .numbufs = p->faxbuf_no
1907 };
1908 int res;
1909
1910 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
1911 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
1912 } else {
1913 p->bufferoverrideinuse = 1;
1914 }
1915 }
1916 p->faxhandled = 1;
1917 if (p->dsp) {
1918 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
1920 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
1921 }
1922 if (strcmp(ast_channel_exten(ast), "fax")) {
1923 const char *target_context = ast_channel_context(ast);
1924
1925 /*
1926 * We need to unlock 'ast' here because ast_exists_extension has the
1927 * potential to start autoservice on the channel. Such action is prone
1928 * to deadlock if the channel is locked.
1929 *
1930 * ast_async_goto() has its own restriction on not holding the
1931 * channel lock.
1932 */
1934 ast_channel_unlock(ast);
1935 if (ast_exists_extension(ast, target_context, "fax", 1,
1936 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
1937 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
1938 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
1939 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
1940 if (ast_async_goto(ast, target_context, "fax", 1))
1941 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
1942 } else {
1943 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
1944 }
1945 ast_channel_lock(ast);
1946 ast_mutex_lock(&p->lock);
1947 } else {
1948 ast_debug(1, "Already in a fax extension, not redirecting\n");
1949 }
1950 } else {
1951 ast_debug(1, "Fax already handled\n");
1952 }
1953 dahdi_confmute(p, 0);
1954 }
1955 p->subs[idx].f.frametype = AST_FRAME_NULL;
1956 p->subs[idx].f.subclass.integer = 0;
1957 *dest = &p->subs[idx].f;
1958 }
1959}

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

3639{
3640 struct dahdi_pvt *p = pvt;
3641
3642 if (neon_mwievent > -1 && !p->mwimonitor_neon)
3643 return;
3644
3645 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
3646 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
3647 notify_message(p->mailbox, 1);
3648 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
3649 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
3650 notify_message(p->mailbox, 0);
3651 }
3652 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
3653 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
3654 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
3655 ast_hangup(chan);
3656 return;
3657 }
3658}

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

2897{
2898 struct dahdi_pvt *p = pvt;
2899
2900 if (!p->hanguponpolarityswitch) {
2901 return;
2902 }
2903
2904 if (p->answeronpolarityswitch) {
2905 my_set_polarity(pvt, 0);
2906 } else {
2907 my_set_polarity(pvt, 1);
2908 }
2909}

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

2660{
2661 struct dahdi_pvt *p = pvt;
2662
2663 return has_voicemail(p);
2664}

References has_voicemail().

◆ my_have_progressdetect()

static int my_have_progressdetect ( void *  pvt)
static

Definition at line 3660 of file chan_dahdi.c.

3661{
3662 struct dahdi_pvt *p = pvt;
3663
3665 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3666 return 1;
3667 } else {
3668 /* Don't have progress detection. */
3669 return 0;
3670 }
3671}

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

3029{
3030 struct dahdi_pvt *p = pvt;
3031 int index;
3032 int x;
3033
3034 index = analogsub_to_dahdisub(sub);
3035
3036 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
3037 ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
3038 return -1;
3039 }
3040
3041 return x;
3042}

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

2795{
2796 struct dahdi_pvt *p = pvt;
2797 int res;
2798 struct dahdi_params par;
2799
2800 memset(&par, 0, sizeof(par));
2801
2802 if (p->subs[SUB_REAL].dfd > -1)
2803 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2804 else {
2805 /* Assume not off hook on CVRS */
2806 res = 0;
2807 par.rxisoffhook = 0;
2808 }
2809 if (res) {
2810 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
2811 }
2812
2813 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
2814 /* When "onhook" that means no battery on the line, and thus
2815 it is out of service..., if it's on a TDM card... If it's a channel
2816 bank, there is no telling... */
2817 return (par.rxbits > -1) || par.rxisoffhook;
2818 }
2819
2820 return par.rxisoffhook;
2821}

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

1962{
1963 struct dahdi_pvt *p = pvt;
1964 ast_mutex_lock(&p->lock);
1965}

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

2494{
2495 ast_callid callid = 0;
2496 int callid_created = ast_callid_threadstorage_auto(&callid);
2497 struct dahdi_pvt *p = pvt;
2498 int dsub = analogsub_to_dahdisub(sub);
2499
2500 return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, NULL, requestor, callid, callid_created);
2501}
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:9614

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

2854{
2855 struct dahdi_pvt *p = pvt;
2856 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2857}

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

3045{
3046 struct dahdi_pvt *p = pvt;
3047 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
3048}

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

2667{
2668 struct dahdi_pvt *p = pvt;
2669 int index;
2670
2671 index = analogsub_to_dahdisub(sub);
2672
2673 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
2674}
static int analog_tone_to_dahditone(enum analog_tone tone)
Definition: chan_dahdi.c:1303

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

2838{
2839 struct dahdi_pvt *p = pvt;
2840
2841 return dahdi_ring_phone(p);
2842}

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

1769{
1770 struct dahdi_pvt *p = pvt;
1771 struct analog_pvt *analog_p = p->sig_pvt;
1772
1773 ast_debug(2, "Starting cid spill\n");
1774
1775 if (p->cidspill) {
1776 ast_log(LOG_WARNING, "cidspill already exists??\n");
1777 ast_free(p->cidspill);
1778 }
1779
1781 int pres = ast_party_id_presentation(&caller->id);
1782 if (cwcid == 0) {
1783 /* Some CPE support additional parameters for on-hook Caller*ID,
1784 * such as redirecting reason and call qualifier, so send those
1785 * if available.
1786 * I don't know of any CPE that supports this for Call Waiting (unfortunately),
1787 * so don't send those for call waiting as that will just lengthen the CID spill
1788 * for no good reason.
1789 */
1791 caller->id.name.str,
1793 NULL,
1794 analog_p->redirecting_reason,
1795 pres,
1796 analog_p->call_qualifier,
1798 AST_LAW(p));
1799 } else {
1800 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
1802 p->callwaitcas = 0;
1803 p->cidcwexpire = 0;
1805 caller->id.name.str,
1807 NULL,
1808 -1,
1809 pres,
1810 0,
1811 AST_LAW(p));
1812 p->cidlen += READ_SIZE * 4;
1813 }
1814 p->cidpos = 0;
1815 p->cid_suppress_expire = 0;
1816 send_callerid(p);
1817 }
1818 return 0;
1819}
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:1253
#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:1247
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:1788
int redirecting_reason
Definition: sig_analog.h:365
unsigned int call_qualifier
Definition: sig_analog.h:357
struct ast_party_caller caller
Definition: sig_analog.h:364

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

2147{
2148 struct dahdi_pvt *p = pvt;
2149
2150 p->inalarm = in_alarm;
2151}

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

2128{
2129 struct dahdi_pvt *p = pvt;
2130
2131 /* Choose proper cadence */
2132 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
2133 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
2134 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
2135 *cid_rings = cidrings[p->distinctivering - 1];
2136 } else {
2137 if (p->distinctivering > 0) {
2138 ast_log(LOG_WARNING, "Cadence %d is not defined, falling back to default ring cadence\n", p->distinctivering);
2139 }
2140 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
2141 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
2142 *cid_rings = p->sendcalleridafter;
2143 }
2144}

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

2277{
2278 struct dahdi_pvt *p = pvt;
2279
2280 p->callwaiting = callwaiting_enable;
2281}

References dahdi_pvt::callwaiting.

◆ my_set_confirmanswer()

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

Definition at line 2260 of file chan_dahdi.c.

2261{
2262 struct dahdi_pvt *p = pvt;
2263 p->confirmanswer = flag;
2264}

References dahdi_pvt::confirmanswer.

◆ my_set_dialing()

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

Definition at line 2153 of file chan_dahdi.c.

2154{
2155 struct dahdi_pvt *p = pvt;
2156
2157 p->dialing = is_dialing;
2158}

References dahdi_pvt::dialing.

◆ my_set_echocanceller()

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

Definition at line 2823 of file chan_dahdi.c.

2824{
2825 struct dahdi_pvt *p = pvt;
2826
2827 if (enable)
2828 dahdi_ec_enable(p);
2829 else
2831
2832 return 0;
2833}

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

2088{
2089 struct dahdi_pvt *p = pvt;
2090 int idx = analogsub_to_dahdisub(sub);
2091
2092 p->subs[idx].inthreeway = inthreeway;
2093}

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

2076{
2077 struct dahdi_pvt *p = pvt;
2078 int oldval;
2079 int idx = analogsub_to_dahdisub(sub);
2080
2081 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
2082 oldval = p->subs[idx].linear;
2083 p->subs[idx].linear = linear_mode ? 1 : 0;
2084 return oldval;
2085}

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

2860{
2861 struct dahdi_pvt *p = pvt;
2863}

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

2305{
2306 struct dahdi_pvt *p = pvt;
2307
2308 p->owner = new_owner;
2309}

References dahdi_pvt::owner.

◆ my_set_outgoing()

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

Definition at line 2160 of file chan_dahdi.c.

2161{
2162 struct dahdi_pvt *p = pvt;
2163
2164 p->outgoing = is_outgoing;
2165}

References dahdi_pvt::outgoing.

◆ my_set_polarity()

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

Definition at line 2865 of file chan_dahdi.c.

2866{
2867 struct dahdi_pvt *p = pvt;
2868
2869 if (p->channel == CHAN_PSEUDO) {
2870 return;
2871 }
2872 p->polarity = value;
2873 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
2874}

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

2299{
2300 struct dahdi_pvt *p = pvt;
2301 p->pulsedial = flag;
2302}

References dahdi_pvt::pulsedial.

◆ my_set_ringtimeout()

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

Definition at line 2203 of file chan_dahdi.c.

2204{
2205 struct dahdi_pvt *p = pvt;
2206 p->ringt = ringt;
2207}

References dahdi_pvt::ringt.

◆ my_set_waitingfordt()

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

Definition at line 2209 of file chan_dahdi.c.

2210{
2211 struct dahdi_pvt *p = pvt;
2212
2213 /* We reset p->waitfordialtonetemp here, to prevent leaking to future calls,
2214 * but we also need to check against this value until we get dialtone
2215 * or the timer expires, since waitingfordt is when the timer started,
2216 * not when it should expire.
2217 *
2218 * Critically, we only set p->waitingfordt here if waitfordialtone or waitfordialtonetemp
2219 * has already been set, as waitingfordt is what is checked at runtime to determine
2220 * if we should be waiting for dial tone. This ensures that if a second call
2221 * is initiated concurrently, the first one "consumes" waitfordialtonetemp and resets it,
2222 * preventing leaking to other calls while remaining available to check on the first one while dialing.
2223 */
2225 p->waitfordialtonetemp = 0;
2226
2228 return;
2229 }
2230
2231 /* Because the DSP is allocated when the channel is created,
2232 * if we requested waitfordialtone later (in a predial handler),
2233 * we need to create it now */
2234 if (!p->dsp) {
2235 p->dsp = ast_dsp_new();
2236 if (!p->dsp) {
2237 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
2238 return;
2239 }
2240 }
2243
2244 ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtoneduration);
2245 gettimeofday(&p->waitingfordt, NULL);
2247}
@ 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 2991 of file chan_dahdi.c.

2992{
2993 struct dahdi_pvt *p = pvt;
2994 int x = DAHDI_START;
2995
2996 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2997}

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

1467{
1468 struct dahdi_pvt *p = pvt;
1469 int index = SUB_REAL;
1471 if (!p->cs) {
1472 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
1473 return -1;
1474 }
1475 bump_gains(p);
1476 dahdi_setlinear(p->subs[index].dfd, 0);
1477
1478 return 0;
1479}

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

2877{
2878 struct dahdi_pvt *p = pvt;
2879
2881 my_set_polarity(pvt, 0);
2882 }
2883}

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

1721{
1722 struct dahdi_pvt *p = pvt;
1723 p->callwaitingrepeat = 0;
1724 p->cidcwexpire = 0;
1725 p->cid_suppress_expire = 0;
1726
1727 return 0;
1728}

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

1484{
1485 struct dahdi_pvt *p = pvt;
1486 int index = SUB_REAL;
1487
1488 if (p->cs) {
1489 callerid_free(p->cs);
1490 }
1491
1492 /* Restore linear mode after Caller*ID processing */
1493 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
1494 restore_gains(p);
1495
1496 return 0;
1497}

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

2450{
2451 struct dahdi_pvt *p = pvt;
2452 int da, db;
2453 int tchan;
2454 int tinthreeway;
2455
2458
2459 tchan = p->subs[da].chan;
2460 p->subs[da].chan = p->subs[db].chan;
2461 p->subs[db].chan = tchan;
2462
2463 tinthreeway = p->subs[da].inthreeway;
2464 p->subs[da].inthreeway = p->subs[db].inthreeway;
2465 p->subs[db].inthreeway = tinthreeway;
2466
2467 p->subs[da].owner = ast_a;
2468 p->subs[db].owner = ast_b;
2469
2470 if (ast_a)
2471 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
2472 if (ast_b)
2473 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
2474
2475 wakeup_sub(p, a);
2476 wakeup_sub(p, b);
2477
2478 return;
2479}
static sqlite3 * db
static void wakeup_sub(struct dahdi_pvt *p, int a)
Definition: chan_dahdi.c:3810
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 3019 of file chan_dahdi.c.

3020{
3021 struct dahdi_pvt *p = pvt;
3022
3023 dahdi_train_ec(p);
3024
3025 return 0;
3026}

References dahdi_train_ec().

◆ my_unallocate_sub()

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

Definition at line 2641 of file chan_dahdi.c.

2642{
2643 struct dahdi_pvt *p = pvt;
2644
2645 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
2646}

References analogsub_to_dahdisub(), and unalloc_sub().

◆ my_unlock_private()

static void my_unlock_private ( void *  pvt)
static

Definition at line 1967 of file chan_dahdi.c.

1968{
1969 struct dahdi_pvt *p = pvt;
1971}

References ast_mutex_unlock, and dahdi_pvt::lock.

◆ my_wait_event()

static int my_wait_event ( void *  pvt)
static

Definition at line 2773 of file chan_dahdi.c.

2774{
2775 struct dahdi_pvt *p = pvt;
2776
2777 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
2778}

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

1872{
1873 struct dahdi_pvt *p = pvt;
1874 int index = analogsub_to_dahdisub(sub);
1875 if (index != SUB_REAL) {
1876 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
1877 }
1878 return dahdi_wink(p, index);
1879}

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

3624{
3625 char s[sizeof(mwimonitornotify) + 164];
3626
3627 if (ast_strlen_zero(mailbox)) {
3628 return;
3629 }
3630
3631 ast_publish_mwi_state(mailbox, NULL, thereornot, thereornot);
3633 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
3634 ast_safe_system(s);
3635 }
3636}
static char mwimonitornotify[PATH_MAX]
Definition: chan_dahdi.c:791
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 7272 of file chan_dahdi.c.

7273{
7274 int res;
7275 char policy_str[21] = "";
7276
7277 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
7278 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
7279 return 1;
7280 }
7281 if (*num_buffers < 0) {
7282 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
7283 return -1;
7284 }
7285 if (!strcasecmp(policy_str, "full")) {
7286 *policy = DAHDI_POLICY_WHEN_FULL;
7287 } else if (!strcasecmp(policy_str, "immediate")) {
7288 *policy = DAHDI_POLICY_IMMEDIATE;
7289#if defined(HAVE_DAHDI_HALF_FULL)
7290 } else if (!strcasecmp(policy_str, "half")) {
7291 *policy = DAHDI_POLICY_HALF_FULL;
7292#endif
7293 } else {
7294 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
7295 return -1;
7296 }
7297
7298 return 0;
7299}

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

18539{
18540 int count_pattern = 0;
18541 int norval = 0;
18542 char *temp = NULL;
18543
18544 for (; ;) {
18545 /* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
18546 if (!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
18547 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18548 break;
18549 }
18550
18551 busy_cadence->pattern[count_pattern] = norval;
18552
18553 count_pattern++;
18554 if (count_pattern == 4) {
18555 break;
18556 }
18557
18558 temp = strchr(v->value, ',');
18559 if (temp == NULL) {
18560 break;
18561 }
18562 v->value = temp + 1;
18563 }
18564 busy_cadence->length = count_pattern;
18565
18566 if (count_pattern % 2 != 0) {
18567 /* The pattern length must be divisible by two */
18568 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18569 }
18570
18571}

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

2945{
2946 struct dahdi_pvt *pvt;
2947
2948 pvt = fxo_pvt(chan);
2949 if (!pvt) {
2950 return -1;
2951 }
2952
2953 snprintf(buffer, buflen, "%d", pvt->polarity);
2954
2955 return 0;
2956}
static struct dahdi_pvt * fxo_pvt(struct ast_channel *chan)
Return DAHDI pivot if channel is FXO signalled.
Definition: chan_dahdi.c:2912

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

2959{
2960 struct dahdi_pvt *pvt;
2961 int polarity;
2962
2963 pvt = fxo_pvt(chan);
2964 if (!pvt) {
2965 return -1;
2966 }
2967
2968 if (!strcasecmp(value, "idle")) {
2970 } else if (!strcasecmp(value, "reverse")) {
2972 } else {
2973 polarity = atoi(value);
2974 }
2975
2977 ast_log(LOG_WARNING, "Invalid polarity: '%s'\n", value);
2978 return -1;
2979 }
2980
2982 return 0;
2983}

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

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

18402{
18403 char *parse = ast_strdupa(data);
18404 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
18405 unsigned int param_count;
18406 unsigned int x;
18407
18408 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
18409 return;
18410
18411 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
18412
18413 /* first parameter is tap length, process it here */
18414
18415 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
18416
18417 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
18418 confp->chan.echocancel.head.tap_length = x;
18419 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
18420 confp->chan.echocancel.head.tap_length = 128;
18421
18422 /* now process any remaining parameters */
18423
18424 for (x = 1; x < param_count; x++) {
18425 struct {
18426 char *name;
18427 char *value;
18428 } param;
18429
18430 if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
18431 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
18432 continue;
18433 }
18434
18435 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
18436 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
18437 continue;
18438 }
18439
18440 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
18441
18442 if (param.value) {
18443 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
18444 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
18445 continue;
18446 }
18447 }
18448 confp->chan.echocancel.head.param_count++;
18449 }
18450}
#define ast_app_separate_args(a, b, c, d)

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

7779{
7780 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7781 RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
7782 if (!dahdi_chan) {
7783 return;
7784 }
7785
7786 ast_str_set(&dahdi_chan, 0, "%d", channel);
7787 body = ast_json_pack("{s: s, s: s}",
7788 "DAHDIChannel", ast_str_buffer(dahdi_chan),
7789 "Alarm", alarm_txt);
7790 if (!body) {
7791 return;
7792 }
7793
7795}
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
Definition: manager.c:638
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 3835 of file chan_dahdi.c.

3836{
3837 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3838 RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
3839 if (!dahdi_chan) {
3840 return;
3841 }
3842
3843 ast_str_set(&dahdi_chan, 0, "%d", channel);
3844 ast_log(LOG_NOTICE, "Alarm cleared on channel DAHDI/%d\n", channel);
3845 body = ast_json_pack("{s: s}", "DAHDIChannel", ast_str_buffer(dahdi_chan));
3846 if (!body) {
3847 return;
3848 }
3849
3850 ast_manager_publish_event("AlarmClear", EVENT_FLAG_SYSTEM, body);
3851}

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

2012{
2013 RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
2014
2015 ast_assert(dahdi_channel != NULL);
2016
2017 blob = ast_json_pack("{s: I, s: i, s: s}",
2018 "group", (ast_json_int_t)group,
2019 "span", span,
2020 "channel", dahdi_channel);
2021 if (!blob) {
2022 return;
2023 }
2024
2025 ast_channel_lock(chan);
2026 ast_channel_publish_blob(chan, dahdichannel_type(), blob);
2027 ast_channel_unlock(chan);
2028}
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 9907 of file chan_dahdi.c.

9908{
9909 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
9910 RAII_VAR(struct ast_str *, dahdichan, ast_str_create(32), ast_free);
9911 if (!dahdichan) {
9912 return;
9913 }
9914
9915 ast_str_set(&dahdichan, 0, "%d", channel);
9916
9917 body = ast_json_pack("{s: s, s: s}",
9918 "DAHDIChannel", ast_str_buffer(dahdichan),
9919 "Status", status);
9920 if (!body) {
9921 return;
9922 }
9923
9925}
jack_status_t status
Definition: app_jack.c:149

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

7765{
7766 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7767
7768 body = ast_json_pack("{s: i, s: s}",
7769 "Span", span,
7770 "Alarm", alarm_txt);
7771 if (!body) {
7772 return;
7773 }
7774
7775 ast_manager_publish_event("SpanAlarm", EVENT_FLAG_SYSTEM, body);
7776}

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

3854{
3855 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3856
3857 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", span);
3858 body = ast_json_pack("{s: i}", "Span", span);
3859 if (!body) {
3860 return;
3861 }
3862
3863 ast_manager_publish_event("SpanAlarmClear", EVENT_FLAG_SYSTEM, body);
3864}

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

1354{
1355#ifdef HAVE_PRI
1356 struct doomed_pri *entry;
1357
1358 AST_LIST_LOCK(&doomed_pris);
1359 while ((entry = AST_LIST_REMOVE_HEAD(&doomed_pris, list))) {
1360 /* The span destruction must be done with this lock not held */
1361 AST_LIST_UNLOCK(&doomed_pris);
1362 ast_debug(4, "Destroying span %d from doomed queue.\n",
1363 entry->pri->span);
1364 pri_destroy_span(entry->pri);
1365 ast_free(entry);
1366 AST_LIST_LOCK(&doomed_pris);
1367 }
1368 AST_LIST_UNLOCK(&doomed_pris);
1369#endif
1370}
#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

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

20616{
20617 int res = 0;
20618
20619 res = setup_dahdi(1);
20620 if (res) {
20621 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
20622 return -1;
20623 }
20624 return 0;
20625}

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

4900{
4901 p->confno = -1;
4902 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
4903 if (p->subs[SUB_REAL].dfd > -1) {
4904 struct dahdi_confinfo zi;
4905
4906 memset(&zi, 0, sizeof(zi));
4907 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
4908 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
4909 }
4910 return 0;
4911}

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

12267{
12268 /* If we're supposed to be stopped -- stay stopped */
12270 return 0;
12272 if (monitor_thread == pthread_self()) {
12274 ast_log(LOG_WARNING, "Cannot kill myself\n");
12275 return -1;
12276 }
12278 /* Wake up the thread */
12279 pthread_kill(monitor_thread, SIGURG);
12280 } else {
12281 /* Start a new monitor */
12284 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12285 return -1;
12286 }
12287 }
12289 return 0;
12290}
static void * do_monitor(void *data)
Definition: chan_dahdi.c:11952

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

5333{
5334 int res;
5335 if (p->saveconf.confmode) {
5336 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
5337 p->saveconf.confmode = 0;
5338 if (res) {
5339 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
5340 return -1;
5341 }
5342 ast_debug(1, "Restored conferencing\n");
5343 }
5344 return 0;
5345}
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 5239 of file chan_dahdi.c.

5240{
5241 int res;
5242
5243 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5244 if (res) {
5245 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
5246 return -1;
5247 }
5248
5249 return 0;
5250}

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

6299{
6300 if (p->bufferoverrideinuse) {
6301 /* faxbuffers are in use, revert them */
6302 struct dahdi_bufferinfo bi = {
6303 .txbufpolicy = p->buf_policy,
6304 .rxbufpolicy = p->buf_policy,
6305 .bufsize = p->bufsize,
6306 .numbufs = p->buf_no
6307 };
6308 int bpres;
6309
6310 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
6311 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
6312 }
6313 p->bufferoverrideinuse = 0;
6314 return bpres;
6315 }
6316
6317 return -1;
6318}

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

5307{
5308 struct dahdi_confinfo c;
5309 int res;
5310 if (p->saveconf.confmode) {
5311 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
5312 return -1;
5313 }
5314 p->saveconf.chan = 0;
5315 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
5316 if (res) {
5317 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
5318 p->saveconf.confmode = 0;
5319 return -1;
5320 }
5321 memset(&c, 0, sizeof(c));
5322 c.confmode = DAHDI_CONF_NORMAL;
5323 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
5324 if (res) {
5325 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
5326 return -1;
5327 }
5328 ast_debug(1, "Disabled conferencing\n");
5329 return 0;
5330}

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

5394{
5395 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
5396 int res;
5397 /* Take out of linear mode if necessary */
5398 if (p->subs[SUB_REAL].linear) {
5399 p->subs[SUB_REAL].linear = 0;
5401 }
5402 while (p->cidpos < p->cidlen) {
5403 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
5404 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
5405 if (res < 0) {
5406 if (errno == EAGAIN)
5407 return 0;
5408 else {
5409 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5410 return -1;
5411 }
5412 }
5413 if (!res)
5414 return 0;
5415 p->cidpos += res;
5416 }
5418 ast_free(p->cidspill);
5419 p->cidspill = NULL;
5420 if (p->callwaitcas) {
5421 /* Wait for CID/CW to expire */
5424 } else
5426 return 0;
5427}
#define CALLWAITING_SUPPRESS_SAMPLES
Definition: chan_dahdi.c:871
#define CIDCW_EXPIRE_SAMPLES
Definition: chan_dahdi.c:872

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

5348{
5349 p->callwaitcas = 0;
5350 p->cidcwexpire = 0;
5351 p->cid_suppress_expire = 0;
5353 return -1;
5355 /* Make sure we account for the end */
5356 p->cidlen += READ_SIZE * 4;
5357 p->cidpos = 0;
5358 send_callerid(p);
5359 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
5360 return 0;
5361}
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:1242
char callwait_num[AST_MAX_EXTENSION]
Call waiting number.
Definition: chan_dahdi.h:547
char callwait_name[AST_MAX_EXTENSION]
Call waiting name.
Definition: chan_dahdi.h:549

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

5221{
5222 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
5223}

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

5204{
5205 struct dahdi_gains g;
5206 int res;
5207
5208 memset(&g, 0, sizeof(g));
5209 res = ioctl(fd, DAHDI_GETGAINS, &g);
5210 if (res) {
5211 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
5212 return res;
5213 }
5214
5215 fill_rxgain(&g, gain, drc, law);
5216
5217 return ioctl(fd, DAHDI_SETGAINS, &g);
5218}
static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
Definition: chan_dahdi.c:5138

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

5187{
5188 struct dahdi_gains g;
5189 int res;
5190
5191 memset(&g, 0, sizeof(g));
5192 res = ioctl(fd, DAHDI_GETGAINS, &g);
5193 if (res) {
5194 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
5195 return res;
5196 }
5197
5198 fill_txgain(&g, gain, drc, law);
5199
5200 return ioctl(fd, DAHDI_SETGAINS, &g);
5201}
static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
Definition: chan_dahdi.c:5088

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

5059{
5060 struct dahdi_hwgain hwgain;
5061
5062 hwgain.newgain = gain * 10.0;
5063 hwgain.tx = tx_direction;
5064 return ioctl(fd, DAHDI_SET_HWGAIN, &hwgain) < 0;
5065}

Referenced by dahdi_set_hwgain(), and mkintf().

◆ setup_dahdi()

static int setup_dahdi ( int  reload)
static

Definition at line 20356 of file chan_dahdi.c.

20357{
20358 int res;
20359 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
20360 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
20362
20363 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
20364 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
20365 } else {
20366 res = -1;
20367 }
20370 ast_cc_config_params_destroy(conf.chan.cc_params);
20371
20372 return res;
20373}

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

20063{
20064 struct ast_config *cfg;
20065 struct ast_config *ucfg;
20066 struct ast_variable *v;
20067 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
20068 const char *chans;
20069 const char *cat;
20070 int res;
20071
20072#ifdef HAVE_PRI
20073 char *c;
20074 int spanno;
20075 int i;
20076 int logicalspan;
20077 int trunkgroup;
20078 int dchannels[SIG_PRI_NUM_DCHANS];
20079#endif
20080 int have_cfg_now;
20081 static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
20082
20083 cfg = ast_config_load(config, config_flags);
20084 have_cfg_now = !!cfg;
20085 if (!cfg) {
20086 /* Error if we have no config file */
20087 if (had_cfg_before) {
20088 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
20090 }
20091 cfg = ast_config_new();/* Dummy config */
20092 if (!cfg) {
20093 return 0;
20094 }
20095 ucfg = ast_config_load("users.conf", config_flags);
20096 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
20097 ast_config_destroy(cfg);
20098 return 0;
20099 }
20100 if (ucfg == CONFIG_STATUS_FILEINVALID) {
20101 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
20102 ast_config_destroy(cfg);
20103 return 0;
20104 }
20105 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
20106 ucfg = ast_config_load("users.conf", config_flags);
20107 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
20108 return 0;
20109 }
20110 if (ucfg == CONFIG_STATUS_FILEINVALID) {
20111 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
20112 return 0;
20113 }
20115 cfg = ast_config_load(config, config_flags);
20116 have_cfg_now = !!cfg;
20117 if (!cfg) {
20118 if (had_cfg_before) {
20119 /* We should have been able to load the config. */
20120 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
20121 ast_config_destroy(ucfg);
20122 return 0;
20123 }
20124 cfg = ast_config_new();/* Dummy config */
20125 if (!cfg) {
20126 ast_config_destroy(ucfg);
20127 return 0;
20128 }
20129 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
20130 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
20131 ast_config_destroy(ucfg);
20132 return 0;
20133 }
20134 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
20135 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
20136 return 0;
20137 } else {
20139 ucfg = ast_config_load("users.conf", config_flags);
20140 if (ucfg == CONFIG_STATUS_FILEINVALID) {
20141 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
20142 ast_config_destroy(cfg);
20143 return 0;
20144 }
20145 }
20146 had_cfg_before = have_cfg_now;
20147
20148 /* It's a little silly to lock it, but we might as well just to be sure */
20150#ifdef HAVE_PRI
20151 if (reload != 1) {
20152 /* Process trunkgroups first */
20153 v = ast_variable_browse(cfg, "trunkgroups");
20154 while (v) {
20155 if (!strcasecmp(v->name, "trunkgroup")) {
20156 trunkgroup = atoi(v->value);
20157 if (trunkgroup > 0) {
20158 if ((c = strchr(v->value, ','))) {
20159 i = 0;
20160 memset(dchannels, 0, sizeof(dchannels));
20161 while (c && (i < SIG_PRI_NUM_DCHANS)) {
20162 dchannels[i] = atoi(c + 1);
20163 if (dchannels[i] < 0) {
20164 ast_log(LOG_WARNING, "D-channel for trunk group %d must be a positive number at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
20165 } else
20166 i++;
20167 c = strchr(c + 1, ',');
20168 }
20169 if (i) {
20170 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
20171 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);
20172 } else
20173 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");
20174 } else
20175 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
20176 } else
20177 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
20178 } else
20179 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
20180 } else if (!strcasecmp(v->name, "spanmap")) {
20181 spanno = atoi(v->value);
20182 if (spanno > 0) {
20183 if ((c = strchr(v->value, ','))) {
20184 trunkgroup = atoi(c + 1);
20185 if (trunkgroup > 0) {
20186 if ((c = strchr(c + 1, ',')))
20187 logicalspan = atoi(c + 1);
20188 else
20189 logicalspan = 0;
20190 if (logicalspan >= 0) {
20191 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
20192 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
20193 } else
20194 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
20195 } else
20196 ast_log(LOG_WARNING, "Logical span must be a positive number, or '0' (for unspecified) at line %d of chan_dahdi.conf\n", v->lineno);
20197 } else
20198 ast_log(LOG_WARNING, "Trunk group must be a positive number at line %d of chan_dahdi.conf\n", v->lineno);
20199 } else
20200 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
20201 } else
20202 ast_log(LOG_WARNING, "Span number must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
20203 } else {
20204 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
20205 }
20206 v = v->next;
20207 }
20208 }
20209#endif
20210
20211 /* Copy the default jb config over global_jbconf */
20212 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
20213
20214 mwimonitornotify[0] = '\0';
20215
20216 v = ast_variable_browse(cfg, "channels");
20217 if ((res = process_dahdi(base_conf,
20218 "" /* Must be empty for the channels category. Silly voicemail mailbox. */,
20219 v, reload, 0))) {
20221 ast_config_destroy(cfg);
20222 if (ucfg) {
20223 ast_config_destroy(ucfg);
20224 }
20225 return res;
20226 }
20227
20228 /* Now get configuration from all normal sections in chan_dahdi.conf: */
20229 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
20230 /* [channels] and [trunkgroups] are used. Let's also reserve
20231 * [globals] and [general] for future use
20232 */
20233 if (!strcasecmp(cat, "general") ||
20234 !strcasecmp(cat, "trunkgroups") ||
20235 !strcasecmp(cat, "globals") ||
20236 !strcasecmp(cat, "channels")) {
20237 continue;
20238 }
20239
20240 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
20241 if (ast_strlen_zero(chans)) {
20242 /* Section is useless without a dahdichan value present. */
20243 continue;
20244 }
20245
20246 /* Copy base_conf to conf. */
20247 deep_copy_dahdi_chan_conf(conf, base_conf);
20248
20249 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
20251 ast_config_destroy(cfg);
20252 if (ucfg) {
20253 ast_config_destroy(ucfg);
20254 }
20255 return res;
20256 }
20257 }
20258
20259 ast_config_destroy(cfg);
20260
20261 if (ucfg) {
20262 /* Reset base_conf, so things don't leak from chan_dahdi.conf */
20263 deep_copy_dahdi_chan_conf(base_conf, default_conf);
20264 process_dahdi(base_conf,
20265 "" /* Must be empty for the general category. Silly voicemail mailbox. */,
20266 ast_variable_browse(ucfg, "general"), 1, 0);
20267
20268 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
20269 if (!strcasecmp(cat, "general")) {
20270 continue;
20271 }
20272
20273 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
20274 if (ast_strlen_zero(chans)) {
20275 /* Section is useless without a dahdichan value present. */
20276 continue;
20277 }
20278
20279 /* Copy base_conf to conf. */
20280 deep_copy_dahdi_chan_conf(conf, base_conf);
20281
20283 ast_config_destroy(ucfg);
20285 return res;
20286 }
20287 }
20288 ast_config_destroy(ucfg);
20289 }
20291
20292#ifdef HAVE_PRI
20293 if (reload != 1) {
20294 int x;
20295 for (x = 0; x < NUM_SPANS; x++) {
20296 if (pris[x].pri.pvts[0] &&
20297 pris[x].pri.master == AST_PTHREADT_NULL) {
20298 prepare_pri(pris + x);
20299 if (sig_pri_start_pri(&pris[x].pri)) {
20300 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
20301 return -1;
20302 } else
20303 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
20304 }
20305 }
20306 }
20307#endif
20308#if defined(HAVE_SS7)
20309 if (reload != 1) {
20310 int x;
20311 for (x = 0; x < NUM_SPANS; x++) {
20312 if (linksets[x].ss7.ss7) {
20313 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
20314 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
20315 return -1;
20316 } else
20317 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
20318 }
20319 }
20320 }
20321#endif /* defined(HAVE_SS7) */
20322#ifdef HAVE_OPENR2
20323 if (reload != 1) {
20324 struct r2link_entry *cur;
20325 int x = 0;
20326 AST_LIST_LOCK(&r2links);
20327 AST_LIST_TRAVERSE(&r2links, cur, list) {
20328 struct dahdi_mfcr2 *r2 = &cur->mfcr2;
20329 if (r2->r2master == AST_PTHREADT_NULL) {
20330 if (ast_pthread_create(&r2->r2master, NULL, mfcr2_monitor, r2)) {
20331 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
20332 return -1;
20333 } else {
20334 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
20335 }
20336 x++;
20337 }
20338 }
20339 AST_LIST_UNLOCK(&r2links);
20340 }
20341#endif
20342 /* And start the monitor for the first time */
20344 return 0;
20345}
static struct chans chans
static struct ast_jb_conf default_jbconf
Definition: chan_dahdi.c:688
static const char config[]
Definition: chan_dahdi.c:739
static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
Definition: chan_dahdi.c:18573
static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
Definition: chan_dahdi.c:20040
#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
@ CONFIG_FLAG_FILEUNCHANGED
#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:869
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
#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 12572 of file chan_dahdi.c.

12573{
12574 return sigtype;
12575}
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 4388 of file chan_dahdi.c.

4389{
4390 int tchan;
4391 int tinthreeway;
4392 struct ast_channel *towner;
4393
4394 ast_debug(1, "Swapping %d and %d\n", a, b);
4395
4396 tchan = p->subs[a].chan;
4397 towner = p->subs[a].owner;
4398 tinthreeway = p->subs[a].inthreeway;
4399
4400 p->subs[a].chan = p->subs[b].chan;
4401 p->subs[a].owner = p->subs[b].owner;
4402 p->subs[a].inthreeway = p->subs[b].inthreeway;
4403
4404 p->subs[b].chan = tchan;
4405 p->subs[b].owner = towner;
4406 p->subs[b].inthreeway = tinthreeway;
4407
4408 if (p->subs[a].owner)
4409 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
4410 if (p->subs[b].owner)
4411 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
4412 wakeup_sub(p, a);
4413 wakeup_sub(p, b);
4414}

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

4535{
4536 if (!x) {
4537 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
4538 return -1;
4539 }
4540 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
4541 dahdi_close_sub(p, x);
4542 p->subs[x].linear = 0;
4543 p->subs[x].chan = 0;
4544 p->subs[x].owner = NULL;
4545 p->subs[x].inthreeway = 0;
4547 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
4548 return 0;
4549}

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

18325{
18326#if defined(HAVE_PRI) || defined(HAVE_SS7)
18327 int y;
18328#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18329#ifdef HAVE_PRI
18330 for (y = 0; y < NUM_SPANS; y++)
18331 ast_mutex_destroy(&pris[y].pri.lock);
18332#endif
18333#if defined(HAVE_SS7)
18334 for (y = 0; y < NUM_SPANS; y++)
18335 ast_mutex_destroy(&linksets[y].ss7.lock);
18336#endif /* defined(HAVE_SS7) */
18337 return __unload_module();
18338}

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

3811{
3813 if (p->subs[a].owner) {
3816 }
3817}
static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
Definition: chan_dahdi.c:3794

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

◆ alarm

int alarm

Definition at line 4690 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 3686 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 779 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 20639 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 771 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 739 of file chan_dahdi.c.

Referenced by setup_dahdi_int().

◆ dahdi_cli

struct ast_cli_entry dahdi_cli[]
static

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

Referenced by setup_dahdi_int().

◆ defaultcic

char defaultcic[64] = ""
static

Definition at line 787 of file chan_dahdi.c.

Referenced by process_dahdi().

◆ defaultozz

char defaultozz[64] = ""
static

Definition at line 788 of file chan_dahdi.c.

Referenced by process_dahdi().

◆ distinctiveringaftercid

int distinctiveringaftercid = 0
static

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

Referenced by do_monitor(), and process_dahdi().

◆ events

const char* const events[]
static

Definition at line 4667 of file chan_dahdi.c.

Referenced by event2str().

◆ global_jbconf

struct ast_jb_conf global_jbconf
static

Definition at line 696 of file chan_dahdi.c.

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

◆ has_pseudo

int has_pseudo
static

Definition at line 758 of file chan_dahdi.c.

Referenced by build_channels(), and process_dahdi().

◆ ifcount

int ifcount = 0
static

Definition at line 819 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 993 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 675 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 831 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 827 of file chan_dahdi.c.

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

◆ mwilevel

int mwilevel = 512
static

Definition at line 803 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 791 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 793 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 755 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 801 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:2944
static int polarity_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: chan_dahdi.c:2958

Definition at line 2985 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

◆ progzone

char progzone[10] = ""
static

Definition at line 796 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

◆ report_alarms

int report_alarms = REPORT_CHANNEL_ALARMS
static

Definition at line 808 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 834 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 881 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 3760 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 986 of file chan_dahdi.c.

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

◆ tdesc

const char tdesc[] = "DAHDI Telephony"
static

Definition at line 718 of file chan_dahdi.c.

◆ usedistinctiveringdetection

int usedistinctiveringdetection = 0
static

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

Referenced by process_dahdi().