Asterisk - The Open Source Telephony Project GIT-master-ff80666
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 REQUIRE_FXO_SIG()
 
#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 int dahdichan_helper (struct ast_channel *chan, char *data, const char *value, char *buffer, size_t buflen)
 
static int dahdichan_read (struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)
 
static int dahdichan_read_property (struct dahdi_pvt *p, struct dahdi_params *dahdip, const char *property, char *buffer, size_t len)
 
static int dahdichan_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 
static int dahdichan_write_property (struct dahdi_pvt *p, struct dahdi_params *dahdip, const char *property, const char *value)
 
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)
 
 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 print_subchannel (struct dahdi_pvt *p, int subchan, char *buffer, size_t len)
 
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_custom_function dahdichan_function
 
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 772 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX

#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)

Definition at line 812 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX_INCOMING

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 811 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX_OUTGOING

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 810 of file chan_dahdi.c.

◆ CALLPROGRESS_PROGRESS

#define CALLPROGRESS_PROGRESS   1

Definition at line 809 of file chan_dahdi.c.

◆ CALLWAITING_REPEAT_SAMPLES

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

10,000 ms

Definition at line 930 of file chan_dahdi.c.

◆ CALLWAITING_SILENT_SAMPLES

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

300 ms

Definition at line 929 of file chan_dahdi.c.

◆ CALLWAITING_SUPPRESS_SAMPLES

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

100 ms

Definition at line 931 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 844 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 845 of file chan_dahdi.c.

◆ CHAN_PSEUDO

#define CHAN_PSEUDO   -2

Definition at line 807 of file chan_dahdi.c.

◆ CIDCW_EXPIRE_SAMPLES

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

500 ms

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

◆ DEFAULT_DIALTONE_DETECT_TIMEOUT

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

10,000 ms

Definition at line 935 of file chan_dahdi.c.

◆ DEFAULT_RINGT

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

8,000 ms

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

◆ GET_CHANNEL

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

Definition at line 1310 of file chan_dahdi.c.

◆ HANGUP

#define HANGUP   1

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

◆ MASK_AVAIL

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 926 of file chan_dahdi.c.

◆ MASK_INUSE

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

◆ MIN_MS_SINCE_FLASH

#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

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

◆ NUM_CADENCE_MAX

#define NUM_CADENCE_MAX   25

Definition at line 814 of file chan_dahdi.c.

◆ NUM_SPANS

#define NUM_SPANS   32

Definition at line 804 of file chan_dahdi.c.

◆ POLARITY_IDLE

#define POLARITY_IDLE   0

Definition at line 1043 of file chan_dahdi.c.

◆ POLARITY_REV

#define POLARITY_REV   1

Definition at line 1044 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 18726 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 18728 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 924 of file chan_dahdi.c.

◆ REPORT_CHANNEL_ALARMS

#define REPORT_CHANNEL_ALARMS   1

Definition at line 866 of file chan_dahdi.c.

◆ REPORT_SPAN_ALARMS

#define REPORT_SPAN_ALARMS   2

Definition at line 867 of file chan_dahdi.c.

◆ REQUIRE_FXO_SIG

#define REQUIRE_FXO_SIG ( )
Value:
if (!(dahdip->sigtype & __DAHDI_SIG_FXO)) { \
ast_log(LOG_WARNING, "DAHDI channel %d is not FXO signalled\n", p->channel); \
return -1; \
}
#define LOG_WARNING

Definition at line 16894 of file chan_dahdi.c.

◆ sig2str

#define sig2str   dahdi_sig2str

Definition at line 4765 of file chan_dahdi.c.

◆ SMDI_MD_WAIT_TIMEOUT

#define SMDI_MD_WAIT_TIMEOUT   1500 /* 1.5 seconds */

Definition at line 733 of file chan_dahdi.c.

◆ TRAILER_MS

#define TRAILER_MS   5

◆ TRANSFER

#define TRANSFER   0

Definition at line 16829 of file chan_dahdi.c.

Function Documentation

◆ __dahdi_exception()

static struct ast_frame * __dahdi_exception ( struct ast_channel ast)
static

Definition at line 8711 of file chan_dahdi.c.

8712{
8713 int res;
8714 int idx;
8715 struct ast_frame *f;
8716 int usedindex = -1;
8717 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8718
8719 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
8720 idx = SUB_REAL;
8721 }
8722
8723 p->subs[idx].f.frametype = AST_FRAME_NULL;
8724 p->subs[idx].f.datalen = 0;
8725 p->subs[idx].f.samples = 0;
8726 p->subs[idx].f.mallocd = 0;
8727 p->subs[idx].f.offset = 0;
8728 p->subs[idx].f.subclass.integer = 0;
8729 p->subs[idx].f.delivery = ast_tv(0,0);
8730 p->subs[idx].f.src = "dahdi_exception";
8731 p->subs[idx].f.data.ptr = NULL;
8732
8733
8734 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
8735 /* If nobody owns us, absorb the event appropriately, otherwise
8736 we loop indefinitely. This occurs when, during call waiting, the
8737 other end hangs up our channel so that it no longer exists, but we
8738 have neither FLASH'd nor ONHOOK'd to signify our desire to
8739 change to the other channel. */
8740 if (p->fake_event) {
8741 res = p->fake_event;
8742 p->fake_event = 0;
8743 } else
8744 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
8745 /* Switch to real if there is one and this isn't something really silly... */
8746 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
8747 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
8748 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
8749 p->owner = p->subs[SUB_REAL].owner;
8750 if (p->owner) {
8752 }
8753 p->subs[SUB_REAL].needunhold = 1;
8754 }
8755 switch (res) {
8756 case DAHDI_EVENT_ONHOOK:
8758 if (p->owner) {
8759 ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
8761 p->callwaitingrepeat = 0;
8762 p->cidcwexpire = 0;
8763 p->cid_suppress_expire = 0;
8764 } else
8765 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8767 break;
8768 case DAHDI_EVENT_RINGOFFHOOK:
8769 dahdi_ec_enable(p);
8770 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
8771 if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
8772 p->subs[SUB_REAL].needanswer = 1;
8773 p->dialing = 0;
8774 }
8775 break;
8776 case DAHDI_EVENT_HOOKCOMPLETE:
8777 case DAHDI_EVENT_RINGERON:
8778 case DAHDI_EVENT_RINGEROFF:
8779 /* Do nothing */
8780 break;
8781 case DAHDI_EVENT_WINKFLASH:
8782 p->flashtime = ast_tvnow();
8783 if (p->owner) {
8784 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
8786 /* Answer if necessary */
8787 usedindex = dahdi_get_index(p->owner, p, 0);
8788 if (usedindex > -1) {
8789 p->subs[usedindex].needanswer = 1;
8790 }
8792 }
8793 p->callwaitingrepeat = 0;
8794 p->cidcwexpire = 0;
8795 p->cid_suppress_expire = 0;
8797 p->subs[SUB_REAL].needunhold = 1;
8798 } else
8799 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8801 break;
8802 default:
8803 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
8804 }
8805 f = &p->subs[idx].f;
8806 return f;
8807 }
8808 if (!(p->radio || (p->oprmode < 0)))
8809 ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
8810 /* If it's not us, return NULL immediately */
8811 if (ast != p->owner) {
8812 if (p->owner) {
8813 ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
8814 }
8815 f = &p->subs[idx].f;
8816 return f;
8817 }
8818
8819 f = dahdi_handle_event(ast);
8820 if (!f) {
8821 const char *name = ast_strdupa(ast_channel_name(ast));
8822
8823 /* Tell the CDR this DAHDI device hung up */
8825 ast_channel_unlock(ast);
8826 ast_set_hangupsource(ast, name, 0);
8827 ast_channel_lock(ast);
8828 ast_mutex_lock(&p->lock);
8829 }
8830 return f;
8831}
#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:7524
char * name
Definition: chan_dahdi.c:4671
static int dahdi_set_hook(int fd, int hs)
Definition: chan_dahdi.c:5232
void dahdi_ec_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4948
void dahdi_conf_update(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4893
static struct ast_frame * dahdi_handle_event(struct ast_channel *ast)
Definition: chan_dahdi.c:7809
static const char * event2str(int event)
Definition: chan_dahdi.c:4692
void dahdi_ec_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5020
static int dahdi_get_event(int fd)
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition: chan_dahdi.c:903
#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:2469
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1255
#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:7368
@ AST_FRAME_NULL
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#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.
struct ast_frame_subclass subclass
struct timeval delivery
enum ast_frame_type frametype
union ast_frame::@231 data
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 20756 of file chan_dahdi.c.

◆ __unload_module()

static int __unload_module ( void  )
static

Definition at line 18401 of file chan_dahdi.c.

18402{
18403 struct dahdi_pvt *p;
18404#if defined(HAVE_PRI) || defined(HAVE_SS7)
18405 int i, j;
18406#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18407
18408#ifdef HAVE_PRI
18409 for (i = 0; i < NUM_SPANS; i++) {
18410 if (pris[i].pri.master != AST_PTHREADT_NULL) {
18411 pthread_cancel(pris[i].pri.master);
18412 pthread_kill(pris[i].pri.master, SIGURG);
18413 }
18414 }
18415 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18416 ast_unregister_application(dahdi_send_keypad_facility_app);
18417#ifdef HAVE_PRI_PROG_W_CAUSE
18418 ast_unregister_application(dahdi_send_callrerouting_facility_app);
18419#endif
18420#endif
18421#if defined(HAVE_SS7)
18422 for (i = 0; i < NUM_SPANS; i++) {
18423 if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
18424 pthread_cancel(linksets[i].ss7.master);
18425 pthread_kill(linksets[i].ss7.master, SIGURG);
18426 }
18427 }
18428 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18429#endif /* defined(HAVE_SS7) */
18430#if defined(HAVE_OPENR2)
18431 dahdi_r2_destroy_links();
18432 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18433 ast_unregister_application(dahdi_accept_r2_call_app);
18434#endif
18435
18438
18440 ast_manager_unregister("DAHDIDialOffhook");
18441 ast_manager_unregister("DAHDIHangup");
18442 ast_manager_unregister("DAHDITransfer");
18443 ast_manager_unregister("DAHDIDNDoff");
18444 ast_manager_unregister("DAHDIDNDon");
18445 ast_manager_unregister("DAHDIShowChannels");
18446 ast_manager_unregister("DAHDIShowStatus");
18447 ast_manager_unregister("DAHDIRestart");
18448#if defined(HAVE_PRI)
18449 ast_manager_unregister("PRIShowSpans");
18450 ast_manager_unregister("PRIDebugSet");
18451 ast_manager_unregister("PRIDebugFileSet");
18452 ast_manager_unregister("PRIDebugFileUnset");
18453#endif /* defined(HAVE_PRI) */
18455
18456 /* Hangup all interfaces if they have an owner */
18458 for (p = iflist; p; p = p->next) {
18459 if (p->owner)
18461 }
18463
18466 pthread_cancel(monitor_thread);
18467 pthread_kill(monitor_thread, SIGURG);
18468 pthread_join(monitor_thread, NULL);
18469 }
18472
18474
18475#if defined(HAVE_PRI)
18476 for (i = 0; i < NUM_SPANS; i++) {
18477 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
18478 pthread_join(pris[i].pri.master, NULL);
18479 }
18480 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
18481 dahdi_close_pri_fd(&(pris[i]), j);
18482 }
18483 sig_pri_stop_pri(&pris[i].pri);
18484 }
18485#if defined(HAVE_PRI_CCSS)
18486 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
18487 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
18488#endif /* defined(HAVE_PRI_CCSS) */
18490#endif
18491
18492#if defined(HAVE_SS7)
18493 for (i = 0; i < NUM_SPANS; i++) {
18494 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
18495 pthread_join(linksets[i].ss7.master, NULL);
18496 }
18497 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
18498 dahdi_close_ss7_fd(&(linksets[i]), j);
18499 }
18500 if (linksets[i].ss7.ss7) {
18501 ss7_destroy(linksets[i].ss7.ss7);
18502 linksets[i].ss7.ss7 = NULL;
18503 }
18504 }
18505#endif /* defined(HAVE_SS7) */
18507
18509
18512 STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
18513 return 0;
18514}
#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:876
#define NUM_SPANS
Definition: chan_dahdi.c:804
static struct dahdi_pvt * iflist
Definition: chan_dahdi.c:1052
static ast_cond_t ss_thread_complete
Definition: chan_dahdi.c:892
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:887
static struct ast_channel_tech dahdi_tech
Definition: chan_dahdi.c:1287
static struct ast_custom_function dahdichan_function
Definition: chan_dahdi.c:17037
static struct ast_custom_function polarity_function
Definition: chan_dahdi.c:17077
static struct ast_cli_entry dahdi_cli[]
Definition: chan_dahdi.c:16814
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:891
static void destroy_all_channels(void)
Definition: chan_dahdi.c:5975
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
@ AST_SOFTHANGUP_APPUNLOAD
Definition: channel.h:1163
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2441
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:7698
#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:703

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, dahdichan_function, 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 20756 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 3742 of file chan_dahdi.c.

3743{
3744 int res;
3745 if (p->subs[SUB_REAL].owner == ast)
3746 res = 0;
3747 else if (p->subs[SUB_CALLWAIT].owner == ast)
3748 res = 1;
3749 else if (p->subs[SUB_THREEWAY].owner == ast)
3750 res = 2;
3751 else {
3752 res = -1;
3753 if (!nullok)
3755 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
3756 ast ? ast_channel_name(ast) : "", p->channel, fname, line);
3757 }
3758 return res;
3759}
#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 17167 of file chan_dahdi.c.

17168{
17169 struct dahdi_pvt *p;
17170 const char *channel = astman_get_header(m, "DAHDIChannel");
17171 const char *number = astman_get_header(m, "Number");
17172 int i;
17173
17174 if (ast_strlen_zero(channel)) {
17175 astman_send_error(s, m, "No channel specified");
17176 return 0;
17177 }
17178 if (ast_strlen_zero(number)) {
17179 astman_send_error(s, m, "No number specified");
17180 return 0;
17181 }
17183 if (!p) {
17184 astman_send_error(s, m, "No such channel");
17185 return 0;
17186 }
17187 if (!p->owner) {
17188 astman_send_error(s, m, "Channel does not have it's owner");
17189 return 0;
17190 }
17191 for (i = 0; i < strlen(number); i++) {
17192 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
17193 dahdi_queue_frame(p, &f);
17194 }
17195 astman_send_ack(s, m, "DAHDIDialOffhook");
17196 return 0;
17197}
static struct dahdi_pvt * find_channel_from_str(const char *channel)
Definition: chan_dahdi.c:16871
static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
Definition: chan_dahdi.c:3799
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1982
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2014
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1643
#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 17102 of file chan_dahdi.c.

17103{
17104 struct dahdi_pvt *p;
17105 const char *channel = astman_get_header(m, "DAHDIChannel");
17106
17107 if (ast_strlen_zero(channel)) {
17108 astman_send_error(s, m, "No channel specified");
17109 return 0;
17110 }
17112 if (!p) {
17113 astman_send_error(s, m, "No such channel");
17114 return 0;
17115 }
17116 dahdi_dnd(p, 0);
17117 astman_send_ack(s, m, "DND Disabled");
17118 return 0;
17119}
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:9927

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

17084{
17085 struct dahdi_pvt *p;
17086 const char *channel = astman_get_header(m, "DAHDIChannel");
17087
17088 if (ast_strlen_zero(channel)) {
17089 astman_send_error(s, m, "No channel specified");
17090 return 0;
17091 }
17093 if (!p) {
17094 astman_send_error(s, m, "No such channel");
17095 return 0;
17096 }
17097 dahdi_dnd(p, 1);
17098 astman_send_ack(s, m, "DND Enabled");
17099 return 0;
17100}

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

16073{
16074 if (dahdi_restart() != 0) {
16075 astman_send_error(s, m, "Failed rereading DAHDI configuration");
16076 return 1;
16077 }
16078 astman_send_ack(s, m, "DAHDIRestart: Success");
16079 return 0;
16080}
static int dahdi_restart(void)
Definition: chan_dahdi.c:15934

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

17200{
17201 struct dahdi_pvt *tmp = NULL;
17202 const char *id = astman_get_header(m, "ActionID");
17203 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
17204 char idText[256];
17205 int channels = 0;
17206 int dahdichanquery;
17207
17208 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
17209 /* Not numeric string. */
17210 dahdichanquery = -1;
17211 }
17212
17213 idText[0] = '\0';
17214 if (!ast_strlen_zero(id)) {
17215 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
17216 }
17217
17218 astman_send_listack(s, m, "DAHDI channel status will follow", "start");
17219
17221
17222 for (tmp = iflist; tmp; tmp = tmp->next) {
17223 if (tmp->channel > 0) {
17224 int alm;
17225
17226 /* If a specific channel is queried for, only deliver status for that channel */
17227 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
17228 continue;
17229
17230 alm = get_alarms(tmp);
17231 channels++;
17232 if (tmp->owner) {
17233 /* Add data if we have a current call */
17234 astman_append(s,
17235 "Event: DAHDIShowChannels\r\n"
17236 "DAHDIChannel: %d\r\n"
17237 "Channel: %s\r\n"
17238 "Uniqueid: %s\r\n"
17239 "AccountCode: %s\r\n"
17240 "Signalling: %s\r\n"
17241 "SignallingCode: %d\r\n"
17242 "Context: %s\r\n"
17243 "DND: %s\r\n"
17244 "Alarm: %s\r\n"
17245 "Description: %s\r\n"
17246 "%s"
17247 "\r\n",
17248 tmp->channel,
17249 ast_channel_name(tmp->owner),
17252 sig2str(tmp->sig),
17253 tmp->sig,
17254 tmp->context,
17255 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
17256 alarm2str(alm),
17257 tmp->description, idText);
17258 } else {
17259 astman_append(s,
17260 "Event: DAHDIShowChannels\r\n"
17261 "DAHDIChannel: %d\r\n"
17262 "Signalling: %s\r\n"
17263 "SignallingCode: %d\r\n"
17264 "Context: %s\r\n"
17265 "DND: %s\r\n"
17266 "Alarm: %s\r\n"
17267 "Description: %s\r\n"
17268 "%s"
17269 "\r\n",
17270 tmp->channel, sig2str(tmp->sig), tmp->sig,
17271 tmp->context,
17272 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
17273 alarm2str(alm),
17274 tmp->description, idText);
17275 }
17276 }
17277 }
17278
17280
17281 astman_send_list_complete_start(s, m, "DAHDIShowChannelsComplete", channels);
17282 astman_append(s, "Items: %d\r\n", channels);
17284 return 0;
17285}
static char * alarm2str(int alm)
Definition: chan_dahdi.c:4682
#define sig2str
Definition: chan_dahdi.c:4765
static int get_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7627
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:2024
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:2060
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2068
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1903
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 17287 of file chan_dahdi.c.

17288{
17289 const char *id = astman_get_header(m, "ActionID");
17290 int span;
17291 int res;
17292 char alarmstr[50];
17293 int ctl;
17294 char idText[256];
17295 int numspans = 0;
17296 struct dahdi_spaninfo spaninfo;
17297
17298 ctl = open("/dev/dahdi/ctl", O_RDWR);
17299 if (ctl < 0) {
17300 astman_send_error(s, m, "No DAHDI detected");
17301 return 0;
17302 }
17303
17304 idText[0] = '\0';
17305 if (!ast_strlen_zero(id)) {
17306 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
17307 }
17308 astman_send_listack(s, m, "DAHDI span statuses will follow", "start");
17309
17310 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
17311 spaninfo.spanno = span;
17312 res = ioctl(ctl, DAHDI_SPANSTAT, &spaninfo);
17313 if (res) {
17314 continue;
17315 }
17316 numspans++;
17317 build_alarm_info(alarmstr, &spaninfo);
17318 astman_append(s,
17319 "Event: DAHDIShowStatus\r\n"
17320 "Span: %d\r\n"
17321 "Description: %s\r\n"
17322 "Alarms: %s\r\n"
17323 "IRQ: %d\r\n"
17324 "bpviol: %d\r\n"
17325 "CRC: %d\r\n"
17326 "Framing: %s\r\n"
17327 "Coding: %s\r\n"
17328 "Options: %s\r\n"
17329 "LBO: %s\r\n"
17330 "%s"
17331 "\r\n",
17332 span, spaninfo.desc, alarmstr, spaninfo.irqmisses, spaninfo.bpvcount, spaninfo.crc4count,
17333 spaninfo.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
17334 spaninfo.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
17335 spaninfo.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
17336 "CAS",
17337 spaninfo.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
17338 spaninfo.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
17339 spaninfo.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
17340 "Unk",
17341 spaninfo.lineconfig & DAHDI_CONFIG_CRC4 ?
17342 spaninfo.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
17343 spaninfo.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
17344 lbostr[spaninfo.lbo],
17345 idText);
17346 }
17347 close(ctl);
17348
17349 astman_send_list_complete_start(s, m, "DAHDIShowStatusComplete", numspans);
17350 astman_append(s, "Items: %d\r\n", numspans);
17352 return 0;
17353}
static void build_alarm_info(char *restrict alarmstr, struct dahdi_spaninfo *spaninfo)
Definition: chan_dahdi.c:16402
static const char *const lbostr[]
Definition: chan_dahdi.c:735

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

17122{
17123 struct dahdi_pvt *p;
17124 const char *channel = astman_get_header(m, "DAHDIChannel");
17125
17126 if (ast_strlen_zero(channel)) {
17127 astman_send_error(s, m, "No channel specified");
17128 return 0;
17129 }
17131 if (!p) {
17132 astman_send_error(s, m, "No such channel");
17133 return 0;
17134 }
17135 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
17136 astman_send_error(s, m, "Channel signaling is not analog");
17137 return 0;
17138 }
17140 astman_send_ack(s, m, "DAHDITransfer");
17141 return 0;
17142}
#define TRANSFER
Definition: chan_dahdi.c:16829
static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
Definition: chan_dahdi.c:16832
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 17144 of file chan_dahdi.c.

17145{
17146 struct dahdi_pvt *p;
17147 const char *channel = astman_get_header(m, "DAHDIChannel");
17148
17149 if (ast_strlen_zero(channel)) {
17150 astman_send_error(s, m, "No channel specified");
17151 return 0;
17152 }
17154 if (!p) {
17155 astman_send_error(s, m, "No such channel");
17156 return 0;
17157 }
17158 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
17159 astman_send_error(s, m, "Channel signaling is not analog");
17160 return 0;
17161 }
17163 astman_send_ack(s, m, "DAHDIHangup");
17164 return 0;
17165}
#define HANGUP
Definition: chan_dahdi.c:16830

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

4683{
4684 int x;
4685 for (x = 0; x < ARRAY_LEN(alarms); x++) {
4686 if (alarms[x].alarm & alm)
4687 return alarms[x].name;
4688 }
4689 return alm ? "Unknown Alarm" : "No Alarm";
4690}
int alarm
Definition: chan_dahdi.c:4670
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 4477 of file chan_dahdi.c.

4478{
4479 struct dahdi_bufferinfo bi;
4480 int res;
4481 if (p->subs[x].dfd >= 0) {
4482 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
4483 return -1;
4484 }
4485
4486 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
4487 if (p->subs[x].dfd <= -1) {
4488 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
4489 return -1;
4490 }
4491
4492 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
4493 if (!res) {
4494 bi.txbufpolicy = p->buf_policy;
4495 bi.rxbufpolicy = p->buf_policy;
4496 bi.numbufs = p->buf_no;
4497 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
4498 if (res < 0) {
4499 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
4500 }
4501 } else
4502 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
4503
4504 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
4505 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
4506 dahdi_close_sub(p, x);
4507 p->subs[x].dfd = -1;
4508 return -1;
4509 }
4510 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
4511 return 0;
4512}
static int dahdi_open(char *fn)
Definition: chan_dahdi.c:4396
static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
Definition: chan_dahdi.c:4449
const char *const subnames[]
Definition: chan_dahdi.c:1046
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 9973 of file chan_dahdi.c.

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

1364{
1365 switch (tone) {
1367 return DAHDI_TONE_RINGTONE;
1369 return DAHDI_TONE_STUTTER;
1371 return DAHDI_TONE_CONGESTION;
1373 return DAHDI_TONE_DIALTONE;
1375 return DAHDI_TONE_DIALRECALL;
1376 case ANALOG_TONE_INFO:
1377 return DAHDI_TONE_INFO;
1378 default:
1379 return -1;
1380 }
1381}
@ 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 1383 of file chan_dahdi.c.

1384{
1385 int index;
1386
1387 switch (analogsub) {
1388 case ANALOG_SUB_REAL:
1389 index = SUB_REAL;
1390 break;
1392 index = SUB_CALLWAIT;
1393 break;
1395 index = SUB_THREEWAY;
1396 break;
1397 default:
1398 ast_log(LOG_ERROR, "Unidentified sub!\n");
1399 index = SUB_REAL;
1400 }
1401
1402 return index;
1403}
@ 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 20756 of file chan_dahdi.c.

◆ attempt_transfer()

static int attempt_transfer ( struct dahdi_pvt p)
static

Definition at line 7568 of file chan_dahdi.c.

7569{
7570 struct ast_channel *owner_real;
7571 struct ast_channel *owner_3way;
7572 enum ast_transfer_result xfer_res;
7573 int res = 0;
7574
7575 owner_real = ast_channel_ref(p->subs[SUB_REAL].owner);
7576 owner_3way = ast_channel_ref(p->subs[SUB_THREEWAY].owner);
7577
7578 ast_verb(3, "TRANSFERRING %s to %s\n",
7579 ast_channel_name(owner_3way), ast_channel_name(owner_real));
7580
7581 ast_channel_unlock(owner_real);
7582 ast_channel_unlock(owner_3way);
7584
7585 xfer_res = ast_bridge_transfer_attended(owner_3way, owner_real);
7586 if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
7588 res = -1;
7589 }
7590
7591 /* Must leave with these locked. */
7592 ast_channel_lock(owner_real);
7593 ast_mutex_lock(&p->lock);
7594
7595 ast_channel_unref(owner_real);
7596 ast_channel_unref(owner_3way);
7597
7598 return res;
7599}
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:4756
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2997
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1141
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3008

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

13566{
13567 struct dahdi_pvt *p = *pvt;
13568
13569 if (p->inalarm)
13570 return 0;
13571
13572 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode))
13573 return analog_available(p->sig_pvt);
13574
13575 switch (p->sig) {
13576#if defined(HAVE_PRI)
13578 {
13579 struct sig_pri_chan *pvt_chan;
13580 int res;
13581
13582 pvt_chan = p->sig_pvt;
13583 res = sig_pri_available(&pvt_chan, is_specific_channel);
13584 *pvt = pvt_chan->chan_pvt;
13585 return res;
13586 }
13587#endif /* defined(HAVE_PRI) */
13588#if defined(HAVE_SS7)
13589 case SIG_SS7:
13590 return sig_ss7_available(p->sig_pvt);
13591#endif /* defined(HAVE_SS7) */
13592 default:
13593 break;
13594 }
13595
13596 if (p->locallyblocked || p->remotelyblocked) {
13597 return 0;
13598 }
13599
13600 /* If no owner definitely available */
13601 if (!p->owner) {
13602#ifdef HAVE_OPENR2
13603 /* Trust MFC/R2 */
13604 if (p->mfcr2) {
13605 if (p->mfcr2call) {
13606 return 0;
13607 } else {
13608 return 1;
13609 }
13610 }
13611#endif
13612 return 1;
13613 }
13614
13615 return 0;
13616}
#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:799
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 16402 of file chan_dahdi.c.

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

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

18533{
18534 char *c, *chan;
18535 int x, start, finish;
18536 struct dahdi_pvt *tmp;
18537
18538 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
18539 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
18540 return -1;
18541 }
18542
18543 c = ast_strdupa(value);
18544
18545 while ((chan = strsep(&c, ","))) {
18546 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
18547 /* Range */
18548 } else if (sscanf(chan, "%30d", &start)) {
18549 /* Just one */
18550 finish = start;
18551 } else if (!strcasecmp(chan, "pseudo")) {
18552 finish = start = CHAN_PSEUDO;
18553 } else {
18554 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
18555 return -1;
18556 }
18557 if (finish < start) {
18558 ast_log(LOG_WARNING, "Silliness: %d < %d\n", start, finish);
18559 x = finish;
18560 finish = start;
18561 start = x;
18562 }
18563
18564 for (x = start; x <= finish; x++) {
18565 if (conf->wanted_channels_start &&
18566 (x < conf->wanted_channels_start ||
18567 x > conf->wanted_channels_end)
18568 ) {
18569 continue;
18570 }
18571 tmp = mkintf(x, conf, reload);
18572
18573 if (tmp) {
18574 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
18575 } else {
18576 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
18577 (reload == 1) ? "reconfigure" : "register", value);
18578 return -1;
18579 }
18580 if (x == CHAN_PSEUDO) {
18581 has_pseudo = 1;
18582 }
18583 }
18584 }
18585
18586 return 0;
18587}
static struct dahdi_pvt * mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
Definition: chan_dahdi.c:12582
static int has_pseudo
Definition: chan_dahdi.c:818
static int reload(void)
Definition: chan_dahdi.c:20732
#define CHAN_PSEUDO
Definition: chan_dahdi.c:807
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 5205 of file chan_dahdi.c.

5206{
5207 int res;
5208
5209 /* Bump receive gain by value stored in cid_rxgain */
5210 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5211 if (res) {
5212 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
5213 return -1;
5214 }
5215
5216 return 0;
5217}
static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
Definition: chan_dahdi.c:5200
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 11173 of file chan_dahdi.c.

11174{
11175 int x;
11176 int sum = 0;
11177
11178 if (!len)
11179 return 0;
11180
11181 for (x = 0; x < len; x++)
11182 sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11183
11184 return sum / len;
11185}
#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 9946 of file chan_dahdi.c.

9947{
9948 int extlen = strlen(exten);
9949
9950 if (!extlen) {
9951 return 1;
9952 }
9953
9954 if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
9955 return 1;
9956 }
9957 /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
9958 if (exten[0] == '*' && extlen < 3) {
9959 if (extlen == 1) {
9960 return 1;
9961 }
9962 /* "*0" should be processed before it gets here */
9963 switch (exten[1]) {
9964 case '6':
9965 case '7':
9966 case '8':
9967 return 1;
9968 }
9969 }
9970 return 0;
9971}

Referenced by analog_ss_thread().

◆ check_for_conference()

static int check_for_conference ( struct dahdi_pvt p)
static

Definition at line 7601 of file chan_dahdi.c.

7602{
7603 struct dahdi_confinfo ci;
7604 /* Fine if we already have a master, etc */
7605 if (p->master || (p->confno > -1))
7606 return 0;
7607 memset(&ci, 0, sizeof(ci));
7608 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
7609 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
7610 return 0;
7611 }
7612 /* If we have no master and don't have a confno, then
7613 if we're in a conference, it's probably a MeetMe room or
7614 some such, so don't let us 3-way out! */
7615 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
7616 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
7617 return 1;
7618 }
7619 return 0;
7620}
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 4767 of file chan_dahdi.c.

4768{
4769 /* If the conference already exists, and we're already in it
4770 don't bother doing anything */
4771 struct dahdi_confinfo zi;
4772
4773 memset(&zi, 0, sizeof(zi));
4774 zi.chan = 0;
4775
4776 if (slavechannel > 0) {
4777 /* If we have only one slave, do a digital mon */
4778 zi.confmode = DAHDI_CONF_DIGITALMON;
4779 zi.confno = slavechannel;
4780 } else {
4781 if (!idx) {
4782 /* Real-side and pseudo-side both participate in conference */
4783 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
4784 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
4785 } else
4786 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
4787 zi.confno = p->confno;
4788 }
4789 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
4790 return 0;
4791 if (c->dfd < 0)
4792 return 0;
4793 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4794 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
4795 return -1;
4796 }
4797 if (slavechannel < 1) {
4798 p->confno = zi.confno;
4799 }
4800 c->curconf = zi;
4801 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4802 return 0;
4803}

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

4817{
4818 struct dahdi_confinfo zi;
4819 if (/* Can't delete if there's no dfd */
4820 (c->dfd < 0) ||
4821 /* Don't delete from the conference if it's not our conference */
4822 !isourconf(p, c)
4823 /* Don't delete if we don't think it's conferenced at all (implied) */
4824 ) return 0;
4825 memset(&zi, 0, sizeof(zi));
4826 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4827 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
4828 return -1;
4829 }
4830 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4831 memcpy(&c->curconf, &zi, sizeof(c->curconf));
4832 return 0;
4833}
static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
Definition: chan_dahdi.c:4805

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

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

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

2099{
2100 char ch_name[23];
2101
2102 if (p->channel < CHAN_PSEUDO) {
2103 /* No B channel */
2104 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
2105 } else if (p->channel == CHAN_PSEUDO) {
2106 /* Pseudo channel */
2107 strcpy(ch_name, "pseudo");
2108 } else {
2109 /* Real channel */
2110 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
2111 }
2112 publish_dahdichannel(chan, p->group, p->span, ch_name);
2113}
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:2071
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 6759 of file chan_dahdi.c.

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

5444{
5445 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5446 int x, res, mysig;
5447 char *dest;
5449 AST_APP_ARG(group); /* channel/group token */
5450 AST_APP_ARG(ext); /* extension token */
5451 //AST_APP_ARG(opts); /* options token */
5452 AST_APP_ARG(other); /* Any remaining unused arguments */
5453 );
5454
5455 ast_mutex_lock(&p->lock);
5456 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
5457
5458 /* Split the dialstring */
5459 dest = ast_strdupa(rdest);
5460 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
5461 if (!args.ext) {
5462 args.ext = "";
5463 }
5464
5465#if defined(HAVE_PRI)
5467 char *subaddr;
5468
5469 sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
5470
5471 /* Remove any subaddress for uniformity with incoming calls. */
5472 subaddr = strchr(p->exten, ':');
5473 if (subaddr) {
5474 *subaddr = '\0';
5475 }
5476 } else
5477#endif /* defined(HAVE_PRI) */
5478 {
5479 ast_copy_string(p->exten, args.ext, sizeof(p->exten));
5480 }
5481
5482 if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
5483 p->subs[SUB_REAL].needbusy = 1;
5485 return 0;
5486 }
5488 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
5490 return -1;
5491 }
5492 p->waitingfordt.tv_sec = 0;
5493 p->dialednone = 0;
5494 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
5495 {
5496 /* Special pseudo -- automatically up */
5499 return 0;
5500 }
5501 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
5502 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
5503 if (res)
5504 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
5505 p->outgoing = 1;
5506
5508 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
5509 } else {
5510 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5511 }
5512
5513#ifdef HAVE_PRI
5515 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
5516 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
5518 return res;
5519 }
5520#endif
5521
5522#if defined(HAVE_SS7)
5523 if (p->sig == SIG_SS7) {
5524 res = sig_ss7_call(p->sig_pvt, ast, rdest);
5526 return res;
5527 }
5528#endif /* defined(HAVE_SS7) */
5529
5530 /* If this is analog signalling we can exit here */
5531 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
5532 p->callwaitrings = 0;
5533 res = analog_call(p->sig_pvt, ast, rdest, timeout);
5535 return res;
5536 }
5537
5538 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
5539 switch (mysig) {
5540 case 0:
5541 /* Special pseudo -- automatically up*/
5543 break;
5544 case SIG_MFCR2:
5545 break;
5546 default:
5547 ast_debug(1, "not yet implemented\n");
5549 return -1;
5550 }
5551
5552#ifdef HAVE_OPENR2
5553 if (p->mfcr2) {
5554 openr2_calling_party_category_t chancat;
5555 int callres = 0;
5556 char *c, *l;
5557
5558 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
5559 p->dialdest[0] = '\0';
5560
5561 c = args.ext;
5562 if (!p->hidecallerid) {
5564 } else {
5565 l = NULL;
5566 }
5567 if (strlen(c) < p->stripmsd) {
5568 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
5570 return -1;
5571 }
5572 p->dialing = 1;
5573 chancat = dahdi_r2_get_channel_category(ast);
5574 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
5575 if (-1 == callres) {
5577 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
5578 return -1;
5579 }
5580 p->mfcr2_call_accepted = 0;
5581 p->mfcr2_progress_sent = 0;
5583 }
5584#endif /* HAVE_OPENR2 */
5586 return 0;
5587}
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:1006
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 5409 of file chan_dahdi.c.

5410{
5411 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5412
5414 if (p->cidspill) {
5415 ast_log(LOG_WARNING, "Spill already exists?!?\n");
5416 ast_free(p->cidspill);
5417 }
5418
5419 /*
5420 * SAS: Subscriber Alert Signal, 440Hz for 300ms
5421 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
5422 */
5423 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
5424 return -1;
5425 save_conference(p);
5426 /* Silence */
5427 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
5428 if (!p->callwaitrings && p->callwaitingcallerid) {
5429 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
5430 p->callwaitcas = 1;
5431 p->cidlen = 2400 + 680 + READ_SIZE * 4;
5432 } else {
5433 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
5434 p->callwaitcas = 0;
5435 p->cidlen = 2400 + READ_SIZE * 4;
5436 }
5437 p->cidpos = 0;
5438 send_callerid(p);
5439
5440 return 0;
5441}
#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:930
static int save_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5286
#define READ_SIZE
Definition: chan_dahdi.c:924
static int send_callerid(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5373
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 14239 of file chan_dahdi.c.

14240{
14241 struct dahdi_pvt *p;
14242 struct dahdi_pvt *exitpvt;
14243 struct dahdi_starting_point start;
14244 int groupmatched = 0;
14245 int channelmatched = 0;
14246
14248 p = determine_starting_point(dest, &start);
14249 if (!p) {
14251 return -1;
14252 }
14253 exitpvt = p;
14254 for (;;) {
14255 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
14256 /* We found a potential match. call the callback */
14257 struct ast_str *device_name;
14258 char *dash;
14259 const char *monitor_type;
14260 char dialstring[AST_CHANNEL_NAME];
14261 char full_device_name[AST_CHANNEL_NAME];
14262
14265 break;
14269#if defined(HAVE_PRI)
14271 /*
14272 * ISDN is in a trunk busy condition so we need to monitor
14273 * the span congestion device state.
14274 */
14275 snprintf(full_device_name, sizeof(full_device_name),
14276 "DAHDI/I%d/congestion", p->pri->span);
14277 } else
14278#endif /* defined(HAVE_PRI) */
14279 {
14280#if defined(HAVE_PRI)
14281 device_name = create_channel_name(p, 1, "");
14282#else
14283 device_name = create_channel_name(p);
14284#endif /* defined(HAVE_PRI) */
14285 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14286 device_name ? ast_str_buffer(device_name) : "");
14287 ast_free(device_name);
14288 /*
14289 * The portion after the '-' in the channel name is either a random
14290 * number, a sequence number, or a subchannel number. None are
14291 * necessary so strip them off.
14292 */
14293 dash = strrchr(full_device_name, '-');
14294 if (dash) {
14295 *dash = '\0';
14296 }
14297 }
14298 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14299
14300 /*
14301 * Analog can only do generic monitoring.
14302 * ISDN is in a trunk busy condition and any "device" is going
14303 * to be busy until a B channel becomes available. The generic
14304 * monitor can do this task.
14305 */
14306 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14307 callback(inbound,
14308#if defined(HAVE_PRI)
14309 p->pri ? p->pri->cc_params : p->cc_params,
14310#else
14311 p->cc_params,
14312#endif /* defined(HAVE_PRI) */
14313 monitor_type, full_device_name, dialstring, NULL);
14314 break;
14315 }
14316 }
14317 p = start.backwards ? p->prev : p->next;
14318 if (!p) {
14319 p = start.backwards ? ifend : iflist;
14320 }
14321 if (p == exitpvt) {
14322 break;
14323 }
14324 }
14326 return 0;
14327}
#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:13532
static struct ast_str * create_channel_name(struct dahdi_pvt *i)
Definition: chan_dahdi.c:9560
static struct dahdi_pvt * ifend
Definition: chan_dahdi.c:1053
static struct dahdi_pvt * determine_starting_point(const char *data, struct dahdi_starting_point *param)
Definition: chan_dahdi.c:13835
#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 1120 of file chan_dahdi.c.

1121{
1122 /* recall that if a field is not included here it is initialized
1123 * to 0 or equivalent
1124 */
1125 struct dahdi_chan_conf conf = {
1126#ifdef HAVE_PRI
1127 .pri.pri = {
1128 .nsf = PRI_NSF_NONE,
1129 .switchtype = PRI_SWITCH_NI2,
1130 .dialplan = PRI_UNKNOWN + 1,
1131 .localdialplan = PRI_NATIONAL_ISDN + 1,
1132 .nodetype = PRI_CPE,
1133 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
1134
1135#if defined(HAVE_PRI_CCSS)
1136 .cc_ptmp_recall_mode = 1,/* specificRecall */
1137 .cc_qsig_signaling_link_req = 1,/* retain */
1138 .cc_qsig_signaling_link_rsp = 1,/* retain */
1139#endif /* defined(HAVE_PRI_CCSS) */
1140
1141 .minunused = 2,
1142 .idleext = "",
1143 .idledial = "",
1144 .internationalprefix = "",
1145 .nationalprefix = "",
1146 .localprefix = "",
1147 .privateprefix = "",
1148 .unknownprefix = "",
1149 .colp_send = SIG_PRI_COLP_UPDATE,
1150 .resetinterval = -1,
1151 },
1152#endif
1153#if defined(HAVE_SS7)
1154 .ss7.ss7 = {
1155 .called_nai = SS7_NAI_NATIONAL,
1156 .calling_nai = SS7_NAI_NATIONAL,
1157 .internationalprefix = "",
1158 .nationalprefix = "",
1159 .subscriberprefix = "",
1160 .unknownprefix = "",
1161 .networkroutedprefix = ""
1162 },
1163#endif /* defined(HAVE_SS7) */
1164#ifdef HAVE_OPENR2
1165 .mfcr2 = {
1166 .variant = OR2_VAR_ITU,
1167 .mfback_timeout = -1,
1168 .metering_pulse_timeout = -1,
1169 .max_ani = 10,
1170 .max_dnis = 4,
1171 .get_ani_first = -1,
1172#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
1173 .skip_category_request = -1,
1174#endif
1175 .call_files = 0,
1176 .allow_collect_calls = 0,
1177 .charge_calls = 1,
1178 .accept_on_offer = 1,
1179 .forced_release = 0,
1180 .double_answer = 0,
1181 .immediate_accept = -1,
1182#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
1183 .dtmf_dialing = -1,
1184 .dtmf_detection = -1,
1185 .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
1186 .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
1187#endif
1188#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
1189 .dtmf_end_timeout = -1,
1190#endif
1191 .logdir = "",
1192 .r2proto_file = "",
1193 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
1194 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
1195 },
1196#endif
1197 .chan = {
1198 .context = "default",
1199 .immediatering = 1,
1200 .cid_num = "",
1201 .cid_name = "",
1202 .cid_tag = "",
1203 .mohinterpret = "default",
1204 .mohsuggest = "",
1205 .parkinglot = "",
1206 .transfertobusy = 1,
1207 .permdialmode = ANALOG_DIALMODE_BOTH,
1208
1209 .ani_info_digits = 2,
1210 .ani_wink_time = 1000,
1211 .ani_timeout = 10000,
1212
1213 .cid_signalling = CID_SIG_BELL,
1214 .cid_start = CID_START_RING,
1215 .dahditrcallerid = 0,
1216 .use_callerid = 1,
1217 .sig = -1,
1218 .outsigmod = -1,
1219
1220 .cid_rxgain = +5.0,
1221
1222 .tonezone = -1,
1223
1224 .echocancel.head.tap_length = 1,
1225
1226 .busycount = 3,
1227
1228 .accountcode = "",
1229
1230 .mailbox = "",
1231
1232#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
1233 .mwisend_fsk = 1,
1234#endif
1235 .polarityonanswerdelay = 600,
1236
1237 .sendcalleridafter = DEFAULT_CIDRINGS,
1238
1239 .buf_policy = DAHDI_POLICY_IMMEDIATE,
1240 .buf_no = numbufs,
1241 .usefaxbuffers = 0,
1242 .cc_params = ast_cc_config_params_init(),
1243 .firstdigit_timeout = ANALOG_FIRST_DIGIT_TIMEOUT,
1244 .interdigit_timeout = ANALOG_INTER_DIGIT_TIMEOUT,
1245 .matchdigit_timeout = ANALOG_MATCH_DIGIT_TIMEOUT,
1246 },
1247 .timing = {
1248 .prewinktime = -1,
1249 .preflashtime = -1,
1250 .winktime = -1,
1251 .flashtime = -1,
1252 .starttime = -1,
1253 .rxwinktime = -1,
1254 .rxflashtime = -1,
1255 .debouncetime = -1
1256 },
1257 .is_sig_auto = 1,
1258 .ignore_failed_channels = 1,
1259 .smdi_port = "/dev/ttyS0",
1260 };
1261
1262 return conf;
1263}
#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:861
#define DEFAULT_CIDRINGS
Typically, how many rings before we should send Caller*ID.
Definition: chan_dahdi.c:770
#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
@ ANALOG_DIALMODE_BOTH
Definition: sig_analog.h:120
#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:1082

References ANALOG_DIALMODE_BOTH, 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 4443 of file chan_dahdi.c.

4444{
4445 if (fd > 0)
4446 close(fd);
4447}

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

4450{
4451 dahdi_close(chan_pvt->subs[sub_num].dfd);
4452 chan_pvt->subs[sub_num].dfd = -1;
4453}
static void dahdi_close(int fd)
Definition: chan_dahdi.c:4443

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

4894{
4895 int needconf = 0;
4896 int x;
4897 int useslavenative;
4898 struct dahdi_pvt *slave = NULL;
4899
4900 useslavenative = isslavenative(p, &slave);
4901 /* Start with the obvious, general stuff */
4902 for (x = 0; x < 3; x++) {
4903 /* Look for three way calls */
4904 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
4905 conf_add(p, &p->subs[x], x, 0);
4906 needconf++;
4907 } else {
4908 conf_del(p, &p->subs[x], x);
4909 }
4910 }
4911 /* If we have a slave, add him to our conference now. or DAX
4912 if this is slave native */
4913 for (x = 0; x < MAX_SLAVES; x++) {
4914 if (p->slaves[x]) {
4915 if (useslavenative)
4916 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
4917 else {
4918 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
4919 needconf++;
4920 }
4921 }
4922 }
4923 /* If we're supposed to be in there, do so now */
4924 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
4925 if (useslavenative)
4926 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
4927 else {
4928 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
4929 needconf++;
4930 }
4931 }
4932 /* If we have a master, add ourselves to his conference */
4933 if (p->master) {
4934 if (isslavenative(p->master, NULL)) {
4936 } else {
4937 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
4938 }
4939 }
4940 if (!needconf) {
4941 /* Nobody is left (or should be left) in our conference.
4942 Kill it. */
4943 p->confno = -1;
4944 }
4945 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
4946}
static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
Definition: chan_dahdi.c:4816
static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
Definition: chan_dahdi.c:4767
static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
Definition: chan_dahdi.c:4835
#define GET_CHANNEL(p)
Definition: chan_dahdi.c:1310
#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 5249 of file chan_dahdi.c.

5250{
5251 int x, res;
5252
5253 x = muted;
5254#if defined(HAVE_PRI) || defined(HAVE_SS7)
5255 switch (p->sig) {
5256#if defined(HAVE_PRI)
5258 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
5259 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
5260 break;
5261 }
5262 /* Fall through */
5263#endif /* defined(HAVE_PRI) */
5264#if defined(HAVE_SS7)
5265 case SIG_SS7:
5266#endif /* defined(HAVE_SS7) */
5267 {
5268 int y = 1;
5269
5270 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
5271 if (res)
5272 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
5273 p->channel, strerror(errno));
5274 }
5275 break;
5276 default:
5277 break;
5278 }
5279#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
5280 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
5281 if (res < 0)
5282 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
5283 return res;
5284}

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

11612{
11613 struct dahdi_pvt *cur;
11614 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
11615 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
11617 int ret = RESULT_FAILURE; /* be pessimistic */
11618
11619 ast_debug(1, "channel range caps: %d - %d\n", start, end);
11621 for (cur = iflist; cur; cur = cur->next) {
11622 if (cur->channel >= start && cur->channel <= end) {
11624 "channel range %d-%d is occupied\n",
11625 start, end);
11626 goto out;
11627 }
11628 }
11629#ifdef HAVE_PRI
11630 {
11631 int i, x;
11632 for (x = 0; x < NUM_SPANS; x++) {
11633 struct dahdi_pri *pri = pris + x;
11634
11635 if (!pris[x].pri.pvts[0]) {
11636 break;
11637 }
11638 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
11639 int channo = pri->dchannels[i];
11640
11641 if (!channo) {
11642 break;
11643 }
11644 if (!pri->pri.fds[i]) {
11645 break;
11646 }
11647 if (channo >= start && channo <= end) {
11649 "channel range %d-%d is occupied by span %d\n",
11650 start, end, x + 1);
11651 goto out;
11652 }
11653 }
11654 }
11655 }
11656#endif
11657 if (!default_conf.chan.cc_params || !base_conf.chan.cc_params ||
11658 !conf.chan.cc_params) {
11659 goto out;
11660 }
11661 default_conf.wanted_channels_start = start;
11662 base_conf.wanted_channels_start = start;
11663 conf.wanted_channels_start = start;
11664 default_conf.wanted_channels_end = end;
11665 base_conf.wanted_channels_end = end;
11666 conf.wanted_channels_end = end;
11667 if (setup_dahdi_int(0, &default_conf, &base_conf, &conf) == 0) {
11668 ret = RESULT_SUCCESS;
11669 }
11670out:
11673 ast_cc_config_params_destroy(conf.chan.cc_params);
11675 return ret;
11676}
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:20241
static struct dahdi_chan_conf dahdi_chan_conf_default(void)
Definition: chan_dahdi.c:1120
#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:1116
struct dahdi_pvt chan
Definition: chan_dahdi.c:1083
int wanted_channels_start
Don't create channels below this number.
Definition: chan_dahdi.c:1110
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 15857 of file chan_dahdi.c.

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

11530{
11531 struct dahdi_pvt *cur;
11532 struct dahdi_pvt *next;
11533 int destroyed_first = 0;
11534 int destroyed_last = 0;
11535
11537 ast_debug(1, "range: %d-%d\n", start, end);
11538 for (cur = iflist; cur; cur = next) {
11539 next = cur->next;
11540 if (cur->channel >= start && cur->channel <= end) {
11541 int x = DAHDI_FLASH;
11542
11543 if (cur->channel > destroyed_last) {
11544 destroyed_last = cur->channel;
11545 }
11546 if (destroyed_first < 1 || cur->channel < destroyed_first) {
11547 destroyed_first = cur->channel;
11548 }
11549 ast_debug(3, "Destroying %d\n", cur->channel);
11550 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11551 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11552
11553 destroy_channel(cur, 1);
11555 }
11556 }
11558 if (destroyed_first > start || destroyed_last < end) {
11559 ast_debug(1, "Asked to destroy %d-%d, destroyed %d-%d,\n",
11560 start, end, destroyed_first, destroyed_last);
11561 }
11562}
static void destroy_channel(struct dahdi_pvt *cur, int now)
Definition: chan_dahdi.c:5957
#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 15813 of file chan_dahdi.c.

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

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

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

1481{
1482 int res;
1483 int offset;
1484 const char *pos;
1485 struct dahdi_dialoperation zo = {
1486 .op = operation,
1487 };
1488
1489 /* Convert the W's to ww. */
1490 pos = dial_str;
1491 for (offset = 0; offset < sizeof(zo.dialstr) - 1; ++offset) {
1492 if (!*pos) {
1493 break;
1494 }
1495 if (*pos == 'W') {
1496 /* Convert 'W' to "ww" */
1497 ++pos;
1498 if (offset >= sizeof(zo.dialstr) - 3) {
1499 /* No room to expand */
1500 break;
1501 }
1502 zo.dialstr[offset] = 'w';
1503 ++offset;
1504 zo.dialstr[offset] = 'w';
1505 continue;
1506 }
1507 zo.dialstr[offset] = *pos++;
1508 }
1509 /* The zo initialization has already terminated the dialstr. */
1510
1511 ast_debug(1, "Channel %d: Dial str '%s' expanded to '%s' sent to DAHDI_DIAL.\n",
1512 pvt->channel, dial_str, zo.dialstr);
1513 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
1514 if (res) {
1515 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
1516 pvt->channel, dial_str, strerror(errno));
1517 }
1518
1519 return res;
1520}

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

4548{
4549 struct dahdi_pvt *pvt;
4550 int idx;
4551 int dtmf;
4552 int res;
4553
4554 pvt = ast_channel_tech_pvt(chan);
4555
4556 ast_mutex_lock(&pvt->lock);
4557
4558 idx = dahdi_get_index(chan, pvt, 0);
4559
4560 if ((idx != SUB_REAL) || !pvt->owner)
4561 goto out;
4562
4563#ifdef HAVE_PRI
4564 switch (pvt->sig) {
4566 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
4567 if (!res)
4568 goto out;
4569 break;
4570 default:
4571 break;
4572 }
4573#endif
4574 dtmf = digit_to_dtmfindex(digit);
4575 if (dtmf == -1) {
4576 /* Not a valid DTMF digit */
4577 goto out;
4578 }
4579
4580 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
4581 char dial_str[] = { 'T', digit, '\0' };
4582
4583 res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
4584 if (!res) {
4585 pvt->dialing = 1;
4586 }
4587 } else {
4588 pvt->dialing = 1;
4589 pvt->begindigit = digit;
4590
4591 /* Flush the write buffer in DAHDI to start sending the digit immediately. */
4592 dtmf = DAHDI_FLUSH_WRITE;
4593 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &dtmf);
4594 if (res) {
4595 ast_log(LOG_WARNING, "Unable to flush the DAHDI write buffer to send DTMF on channel %d: %s\n",
4596 pvt->channel, strerror(errno));
4597 }
4598
4599 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
4600 ast_channel_name(chan), digit);
4601 }
4602
4603out:
4604 ast_mutex_unlock(&pvt->lock);
4605
4606 return 0;
4607}
char digit
static int digit_to_dtmfindex(char digit)
Definition: chan_dahdi.c:4531
static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
Definition: chan_dahdi.c:1480
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 4609 of file chan_dahdi.c.

4610{
4611 struct dahdi_pvt *pvt;
4612 int res = 0;
4613 int idx;
4614 int x;
4615
4616 pvt = ast_channel_tech_pvt(chan);
4617
4618 ast_mutex_lock(&pvt->lock);
4619
4620 idx = dahdi_get_index(chan, pvt, 0);
4621
4622 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
4623 goto out;
4624
4625#ifdef HAVE_PRI
4626 /* This means that the digit was already sent via PRI signalling */
4627 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
4628 goto out;
4629 }
4630#endif
4631
4632 if (pvt->begindigit) {
4633 x = -1;
4634 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
4635 ast_channel_name(chan), digit);
4636 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
4637 pvt->dialing = 0;
4638 pvt->begindigit = 0;
4639 }
4640
4641out:
4642 ast_mutex_unlock(&pvt->lock);
4643
4644 return res;
4645}

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

9928{
9929 if (dahdi_analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
9930 return analog_dnd(dahdichan->sig_pvt, flag);
9931 }
9932
9933 if (flag == -1) {
9934 return dahdichan->dnd;
9935 }
9936
9937 /* Do not disturb */
9938 dahdichan->dnd = flag;
9939 ast_verb(3, "%s DND on channel %d\n",
9940 flag? "Enabled" : "Disabled",
9941 dahdichan->channel);
9942 publish_dnd_state(dahdichan->channel, flag ? "enabled" : "disabled");
9943 return 0;
9944}
static void publish_dnd_state(int channel, const char *status)
Definition: chan_dahdi.c:9898
long int flag
Definition: f2c.h:83
int analog_dnd(struct analog_pvt *p, int flag)
Definition: sig_analog.c:4453
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 6823 of file chan_dahdi.c.

6824{
6825 int val = 0;
6826
6827 p->ignoredtmf = 1;
6828
6829 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6830
6831 if (!p->hardwaredtmf && p->dsp) {
6832 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
6834 }
6835}
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1770
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 6837 of file chan_dahdi.c.

6838{
6839 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
6840
6841 if (p->channel == CHAN_PSEUDO)
6842 return;
6843
6844 p->ignoredtmf = 0;
6845
6846 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6847
6848 if (!p->hardwaredtmf && p->dsp) {
6851 }
6852}
#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 5020 of file chan_dahdi.c.

5021{
5022 int res;
5023
5024 if (p->echocanon) {
5025 struct dahdi_echocanparams ecp = { .tap_length = 0 };
5026
5027 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
5028
5029 if (res)
5030 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
5031 else
5032 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
5033 }
5034
5035 p->echocanon = 0;
5036}
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 4948 of file chan_dahdi.c.

4949{
4950 int res;
4951 if (!p)
4952 return;
4953 if (p->echocanon) {
4954 ast_debug(1, "Echo cancellation already on\n");
4955 return;
4956 }
4957 if (p->digital) {
4958 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
4959 return;
4960 }
4961 if (p->echocancel.head.tap_length) {
4962#if defined(HAVE_PRI) || defined(HAVE_SS7)
4963 switch (p->sig) {
4964#if defined(HAVE_PRI)
4966 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
4967 /*
4968 * PRI nobch pseudo channel. Does not need ec anyway.
4969 * Does not handle ioctl(DAHDI_AUDIOMODE)
4970 */
4971 return;
4972 }
4973 /* Fall through */
4974#endif /* defined(HAVE_PRI) */
4975#if defined(HAVE_SS7)
4976 case SIG_SS7:
4977#endif /* defined(HAVE_SS7) */
4978 {
4979 int x = 1;
4980
4981 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
4982 if (res)
4984 "Unable to enable audio mode on channel %d (%s)\n",
4985 p->channel, strerror(errno));
4986 }
4987 break;
4988 default:
4989 break;
4990 }
4991#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
4992 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
4993 if (res) {
4994 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
4995 } else {
4996 p->echocanon = 1;
4997 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
4998 }
4999 } else
5000 ast_debug(1, "No echo cancellation requested\n");
5001}
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 8833 of file chan_dahdi.c.

8834{
8835 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8836 struct ast_frame *f;
8837 ast_mutex_lock(&p->lock);
8838 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8839 struct analog_pvt *analog_p = p->sig_pvt;
8840 f = analog_exception(analog_p, ast);
8841 } else {
8842 f = __dahdi_exception(ast);
8843 }
8845 return f;
8846}
static struct ast_frame * __dahdi_exception(struct ast_channel *ast)
Definition: chan_dahdi.c:8711
struct ast_frame * analog_exception(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:3960

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

16833{
16834 if (p) {
16835 switch (mode) {
16836 case TRANSFER:
16837 p->fake_event = DAHDI_EVENT_WINKFLASH;
16838 break;
16839 case HANGUP:
16840 p->fake_event = DAHDI_EVENT_ONHOOK;
16841 break;
16842 default:
16843 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));
16844 }
16845 }
16846 return 0;
16847}

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

7485{
7486 struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
7487 int x;
7488
7489 ast_mutex_lock(&p->lock);
7490
7491 ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
7492 if (p->owner == oldchan) {
7493 p->owner = newchan;
7494 }
7495 for (x = 0; x < 3; x++) {
7496 if (p->subs[x].owner == oldchan) {
7497 if (!x) {
7499 }
7500 p->subs[x].owner = newchan;
7501 }
7502 }
7503 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
7504 analog_fixup(oldchan, newchan, p->sig_pvt);
7505#if defined(HAVE_PRI)
7506 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
7507 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
7508#endif /* defined(HAVE_PRI) */
7509#if defined(HAVE_SS7)
7510 } else if (p->sig == SIG_SS7) {
7511 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
7512#endif /* defined(HAVE_SS7) */
7513 }
7515
7517
7518 if (ast_channel_state(newchan) == AST_STATE_RINGING) {
7520 }
7521 return 0;
7522}
static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Definition: chan_dahdi.c:9433
void dahdi_master_slave_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
Definition: chan_dahdi.c:7404
@ AST_CONTROL_RINGING
int analog_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, void *newp)
Definition: sig_analog.c:4415
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 7122 of file chan_dahdi.c.

7123{
7124 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
7125 int res = 0;
7126
7127 if (!p) {
7128 /* No private structure! */
7129 *buf = '\0';
7130 return -1;
7131 }
7132
7133 if (!strcasecmp(data, "rxgain")) {
7134 ast_mutex_lock(&p->lock);
7135 snprintf(buf, len, "%f", p->rxgain);
7137 } else if (!strcasecmp(data, "txgain")) {
7138 ast_mutex_lock(&p->lock);
7139 snprintf(buf, len, "%f", p->txgain);
7141 } else if (!strcasecmp(data, "dahdi_channel")) {
7142 ast_mutex_lock(&p->lock);
7143 snprintf(buf, len, "%d", p->channel);
7145 } else if (!strcasecmp(data, "dahdi_span")) {
7146 ast_mutex_lock(&p->lock);
7147 snprintf(buf, len, "%d", p->span);
7149 } else if (!strcasecmp(data, "dahdi_group")) {
7150 ast_mutex_lock(&p->lock);
7151 snprintf(buf, len, "%llu", p->group);
7153 } else if (!strcasecmp(data, "dahdi_type")) {
7154 ast_mutex_lock(&p->lock);
7155 switch (p->sig) {
7156#if defined(HAVE_OPENR2)
7157 case SIG_MFCR2:
7158 ast_copy_string(buf, "mfc/r2", len);
7159 break;
7160#endif /* defined(HAVE_OPENR2) */
7161#if defined(HAVE_PRI)
7163 ast_copy_string(buf, "pri", len);
7164 break;
7165#endif /* defined(HAVE_PRI) */
7166 case 0:
7167 ast_copy_string(buf, "pseudo", len);
7168 break;
7169#if defined(HAVE_SS7)
7170 case SIG_SS7:
7171 ast_copy_string(buf, "ss7", len);
7172 break;
7173#endif /* defined(HAVE_SS7) */
7174 default:
7175 /* The only thing left is analog ports. */
7176 ast_copy_string(buf, "analog", len);
7177 break;
7178 }
7180#if defined(HAVE_PRI)
7181#if defined(HAVE_PRI_REVERSE_CHARGE)
7182 } else if (!strcasecmp(data, "reversecharge")) {
7183 ast_mutex_lock(&p->lock);
7184 switch (p->sig) {
7186 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
7187 break;
7188 default:
7189 *buf = '\0';
7190 res = -1;
7191 break;
7192 }
7194#endif
7195#if defined(HAVE_PRI_SETUP_KEYPAD)
7196 } else if (!strcasecmp(data, "keypad_digits")) {
7197 ast_mutex_lock(&p->lock);
7198 switch (p->sig) {
7200 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
7201 len);
7202 break;
7203 default:
7204 *buf = '\0';
7205 res = -1;
7206 break;
7207 }
7209#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
7210 } else if (!strcasecmp(data, "no_media_path")) {
7211 ast_mutex_lock(&p->lock);
7212 switch (p->sig) {
7214 /*
7215 * TRUE if the call is on hold or is call waiting because
7216 * there is no media path available.
7217 */
7218 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
7219 break;
7220 default:
7221 *buf = '\0';
7222 res = -1;
7223 break;
7224 }
7226#endif /* defined(HAVE_PRI) */
7227 } else if (!strcasecmp(data, "dialmode")) {
7228 struct analog_pvt *analog_p;
7229 ast_mutex_lock(&p->lock);
7230 analog_p = p->sig_pvt;
7231 /* Hardcode p->radio and p->oprmode as 0 since we're using this to check for analogness, not the handler */
7232 if (dahdi_analog_lib_handles(p->sig, 0, 0) && analog_p) {
7233 switch (analog_p->dialmode) {
7235 ast_copy_string(buf, "both", len);
7236 break;
7238 ast_copy_string(buf, "pulse", len);
7239 break;
7241 ast_copy_string(buf, "dtmf", len);
7242 break;
7244 ast_copy_string(buf, "none", len);
7245 break;
7246 }
7247 } else {
7248 ast_log(LOG_WARNING, "%s only supported on analog channels\n", data);
7249 *buf = '\0';
7250 res = -1;
7251 }
7253 } else {
7254 *buf = '\0';
7255 res = -1;
7256 }
7257
7258 return res;
7259}
@ ANALOG_DIALMODE_DTMF
Definition: sig_analog.h:122
@ ANALOG_DIALMODE_PULSE
Definition: sig_analog.h:121
@ ANALOG_DIALMODE_NONE
Definition: sig_analog.h:123
enum analog_dialmode dialmode
Definition: sig_analog.h:324

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

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

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

904{
905 int j;
906 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
907 return -1;
908 return j;
909}

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

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

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

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

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

5651{
5652 /* Extract from the forward chain. */
5653 if (pvt->prev) {
5654 pvt->prev->next = pvt->next;
5655 } else if (iflist == pvt) {
5656 /* Node is at the head of the list. */
5657 iflist = pvt->next;
5658 }
5659
5660 /* Extract from the reverse chain. */
5661 if (pvt->next) {
5662 pvt->next->prev = pvt->prev;
5663 } else if (ifend == pvt) {
5664 /* Node is at the end of the list. */
5665 ifend = pvt->prev;
5666 }
5667
5668 /* Node is no longer in the list. */
5670 pvt->prev = NULL;
5671 pvt->next = NULL;
5672}
@ 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 5602 of file chan_dahdi.c.

5603{
5604 struct dahdi_pvt *cur;
5605
5607
5608 /* Find place in middle of list for the new interface. */
5609 for (cur = iflist; cur; cur = cur->next) {
5610 if (pvt->channel < cur->channel) {
5611 /* New interface goes before the current interface. */
5612 pvt->prev = cur->prev;
5613 pvt->next = cur;
5614 if (cur->prev) {
5615 /* Insert into the middle of the list. */
5616 cur->prev->next = pvt;
5617 } else {
5618 /* Insert at head of list. */
5619 iflist = pvt;
5620 }
5621 cur->prev = pvt;
5622 return;
5623 }
5624 }
5625
5626 /* New interface goes onto the end of the list */
5627 pvt->prev = ifend;
5628 pvt->next = NULL;
5629 if (ifend) {
5630 ifend->next = pvt;
5631 }
5632 ifend = pvt;
5633 if (!iflist) {
5634 /* List was empty */
5635 iflist = pvt;
5636 }
5637}
@ 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 9433 of file chan_dahdi.c.

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

3775{
3776 for (;;) {
3777 if (!pvt->subs[sub_idx].owner) {
3778 /* No subchannel owner pointer */
3779 break;
3780 }
3781 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
3782 /* Got subchannel owner lock */
3783 break;
3784 }
3785 /* We must unlock the private to avoid the possibility of a deadlock */
3786 DEADLOCK_AVOIDANCE(&pvt->lock);
3787 }
3788}
#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 7460 of file chan_dahdi.c.

7461{
7462 int x;
7463 if (!slave || !master) {
7464 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
7465 return;
7466 }
7467 for (x = 0; x < MAX_SLAVES; x++) {
7468 if (!master->slaves[x]) {
7469 master->slaves[x] = slave;
7470 break;
7471 }
7472 }
7473 if (x >= MAX_SLAVES) {
7474 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
7475 master->slaves[MAX_SLAVES - 1] = slave;
7476 }
7477 if (slave->master)
7478 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
7479 slave->master = master;
7480
7481 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
7482}

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

7405{
7406 /* Unlink a specific slave or all slaves/masters from a given master */
7407 int x;
7408 int hasslaves;
7409 if (!master)
7410 return;
7411 if (needlock) {
7412 ast_mutex_lock(&master->lock);
7413 if (slave) {
7414 while (ast_mutex_trylock(&slave->lock)) {
7415 DEADLOCK_AVOIDANCE(&master->lock);
7416 }
7417 }
7418 }
7419 hasslaves = 0;
7420 for (x = 0; x < MAX_SLAVES; x++) {
7421 if (master->slaves[x]) {
7422 if (!slave || (master->slaves[x] == slave)) {
7423 /* Take slave out of the conference */
7424 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
7425 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
7426 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
7427 master->slaves[x]->master = NULL;
7428 master->slaves[x] = NULL;
7429 } else
7430 hasslaves = 1;
7431 }
7432 if (!hasslaves)
7433 master->inconference = 0;
7434 }
7435 if (!slave) {
7436 if (master->master) {
7437 /* Take master out of the conference */
7438 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
7439 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
7440 hasslaves = 0;
7441 for (x = 0; x < MAX_SLAVES; x++) {
7442 if (master->master->slaves[x] == master)
7443 master->master->slaves[x] = NULL;
7444 else if (master->master->slaves[x])
7445 hasslaves = 1;
7446 }
7447 if (!hasslaves)
7448 master->master->inconference = 0;
7449 }
7450 master->master = NULL;
7451 }
7452 dahdi_conf_update(master);
7453 if (needlock) {
7454 if (slave)
7455 ast_mutex_unlock(&slave->lock);
7456 ast_mutex_unlock(&master->lock);
7457 }
7458}
#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 9614 of file chan_dahdi.c.

9615{
9616 struct ast_channel *tmp;
9617 struct ast_format_cap *caps;
9618 struct ast_format *deflaw;
9619 int x;
9620 int features;
9621 struct ast_str *chan_name;
9622 struct ast_variable *v;
9623 char *dashptr;
9624 char device_name[AST_CHANNEL_NAME];
9625
9626 if (i->subs[idx].owner) {
9627 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
9628 return NULL;
9629 }
9630
9631#if defined(HAVE_PRI)
9632 /*
9633 * The dnid has been stuffed with the called-number[:subaddress]
9634 * by dahdi_request() for outgoing calls.
9635 */
9636 chan_name = create_channel_name(i, i->outgoing, i->dnid);
9637#else
9638 chan_name = create_channel_name(i);
9639#endif /* defined(HAVE_PRI) */
9640 if (!chan_name) {
9641 return NULL;
9642 }
9643
9645 if (!caps) {
9646 ast_free(chan_name);
9647 return NULL;
9648 }
9649
9650 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));
9651 ast_free(chan_name);
9652 if (!tmp) {
9653 ao2_ref(caps, -1);
9654 return NULL;
9655 }
9656
9658
9659 if (callid) {
9660 ast_channel_callid_set(tmp, callid);
9661 }
9662
9664#if defined(HAVE_PRI)
9665 if (i->pri) {
9667 }
9668#endif /* defined(HAVE_PRI) */
9670 if (law) {
9671 i->law = law;
9672 if (law == DAHDI_LAW_ALAW) {
9673 deflaw = ast_format_alaw;
9674 } else {
9675 deflaw = ast_format_ulaw;
9676 }
9677 } else {
9678 switch (i->sig) {
9680 /* Make sure companding law is known. */
9681 i->law = (i->law_default == DAHDI_LAW_ALAW)
9682 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
9683 break;
9684 default:
9685 i->law = i->law_default;
9686 break;
9687 }
9688 if (i->law_default == DAHDI_LAW_ALAW) {
9689 deflaw = ast_format_alaw;
9690 } else {
9691 deflaw = ast_format_ulaw;
9692 }
9693 }
9694 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
9695 ast_format_cap_append(caps, deflaw, 0);
9697 ao2_ref(caps, -1);
9698 /* Start out assuming ulaw since it's smaller :) */
9699 ast_channel_set_rawreadformat(tmp, deflaw);
9700 ast_channel_set_readformat(tmp, deflaw);
9701 ast_channel_set_rawwriteformat(tmp, deflaw);
9702 ast_channel_set_writeformat(tmp, deflaw);
9703 i->subs[idx].linear = 0;
9704 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
9705 features = 0;
9706 if (idx == SUB_REAL) {
9707 if (i->busydetect && CANBUSYDETECT(i))
9708 features |= DSP_FEATURE_BUSY_DETECT;
9710 features |= DSP_FEATURE_CALL_PROGRESS;
9712 features |= DSP_FEATURE_WAITDIALTONE;
9713 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
9715 features |= DSP_FEATURE_FAX_DETECT;
9716 }
9717 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
9718 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
9719 i->hardwaredtmf = 0;
9720 features |= DSP_FEATURE_DIGIT_DETECT;
9721 } else if (NEED_MFDETECT(i)) {
9722 i->hardwaredtmf = 1;
9723 features |= DSP_FEATURE_DIGIT_DETECT;
9724 }
9725 }
9726 if (features) {
9727 if (i->dsp) {
9728 ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
9729 } else {
9730 if (i->channel != CHAN_PSEUDO)
9731 i->dsp = ast_dsp_new();
9732 else
9733 i->dsp = NULL;
9734 if (i->dsp) {
9735 i->dsp_features = features;
9736#if defined(HAVE_PRI) || defined(HAVE_SS7)
9737 /* We cannot do progress detection until receive PROGRESS message */
9738 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
9739 /* Remember requested DSP features, don't treat
9740 talking as ANSWER */
9741 i->dsp_features = features & ~DSP_PROGRESS_TALK;
9742 features = 0;
9743 }
9744#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9745 ast_dsp_set_features(i->dsp, features);
9749 if (i->busydetect && CANBUSYDETECT(i)) {
9752 }
9753 }
9754 }
9755 }
9756
9758
9759 if (state == AST_STATE_RING)
9760 ast_channel_rings_set(tmp, 1);
9762 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
9763 /* Only FXO signalled stuff can be picked up */
9768 }
9769 if (!ast_strlen_zero(i->parkinglot))
9770 ast_channel_parkinglot_set(tmp, i->parkinglot);
9771 if (!ast_strlen_zero(i->language))
9772 ast_channel_language_set(tmp, i->language);
9773 if (!i->owner)
9774 i->owner = tmp;
9776 ast_channel_accountcode_set(tmp, i->accountcode);
9777 if (i->amaflags)
9779 i->subs[idx].owner = tmp;
9781 if (!dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
9782 ast_channel_call_forward_set(tmp, i->call_forward);
9783 }
9784 /* If we've been told "no ADSI" then enforce it */
9785 if (!i->adsi)
9787 if (!ast_strlen_zero(i->exten))
9789 if (!ast_strlen_zero(i->rdnis)) {
9792 }
9793 if (!ast_strlen_zero(i->dnid)) {
9795 }
9796
9797 /* Don't use ast_set_callerid() here because it will
9798 * generate a needless NewCallerID event */
9799#if defined(HAVE_PRI) || defined(HAVE_SS7)
9800 if (!ast_strlen_zero(i->cid_ani)) {
9802 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_ani);
9803 } else if (!ast_strlen_zero(i->cid_num)) {
9806 }
9807#else
9808 if (!ast_strlen_zero(i->cid_num)) {
9811 }
9812#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9816 ast_channel_caller(tmp)->ani2 = i->cid_ani2;
9818 /* clear the fake event in case we posted one before we had ast_channel */
9819 i->fake_event = 0;
9820 /* Assure there is no confmute on this channel */
9821 dahdi_confmute(i, 0);
9822 i->muting = 0;
9823 /* Configure the new channel jb */
9825
9826 /* Set initial device state */
9827 ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
9828 dashptr = strrchr(device_name, '-');
9829 if (dashptr) {
9830 *dashptr = '\0';
9831 }
9834
9835 for (v = i->vars ; v ; v = v->next)
9837
9839
9840 ast_channel_unlock(tmp);
9841
9843
9845 if (startpbx) {
9846#ifdef HAVE_OPENR2
9847 if (i->mfcr2call) {
9848 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
9849 }
9850#endif
9851 if (ast_pbx_start(tmp)) {
9852 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
9853 ast_hangup(tmp);
9854 return NULL;
9855 }
9856 }
9857 return tmp;
9858}
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:811
#define CALLPROGRESS_FAX_OUTGOING
Definition: chan_dahdi.c:810
static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
Definition: chan_dahdi.c:2098
static struct ast_jb_conf global_jbconf
Definition: chan_dahdi.c:756
static char progzone[10]
Definition: chan_dahdi.c:856
#define CANBUSYDETECT(p)
Definition: chan_dahdi.c:844
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:10465
@ AST_FLAG_DISABLE_DEVSTATE_CACHE
Definition: channel.h:1049
@ 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)
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:2396
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:1806
#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:1795
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1760
int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
Set zone for doing progress detection.
Definition: dsp.c:1894
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:4729
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Definition of a media format.
Definition: format.c:43
char * str
Subscriber phone number (Malloced)
Definition: channel.h:388
struct ast_party_dialed::@213 number
Dialed/Called number.
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 9605 of file chan_dahdi.c.

9606{
9607 struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, assignedids, requestor, callid);
9608
9610
9611 return new_channel;
9612}
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 4396 of file chan_dahdi.c.

4397{
4398 int fd;
4399 int isnum;
4400 int chan = 0;
4401 int bs;
4402 int x;
4403 isnum = 1;
4404 for (x = 0; x < strlen(fn); x++) {
4405 if (!isdigit(fn[x])) {
4406 isnum = 0;
4407 break;
4408 }
4409 }
4410 if (isnum) {
4411 chan = atoi(fn);
4412 if (chan < 1) {
4413 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
4414 return -1;
4415 }
4416 fn = "/dev/dahdi/channel";
4417 }
4418 fd = open(fn, O_RDWR | O_NONBLOCK);
4419 if (fd < 0) {
4420 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
4421 return -1;
4422 }
4423 if (chan) {
4424 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
4425 x = errno;
4426 close(fd);
4427 errno = x;
4428 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
4429 return -1;
4430 }
4431 }
4432 bs = READ_SIZE;
4433 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
4434 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
4435 x = errno;
4436 close(fd);
4437 errno = x;
4438 return -1;
4439 }
4440 return fd;
4441}
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 6854 of file chan_dahdi.c.

6855{
6856 char *cp;
6857 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
6858
6859 /* all supported options require data */
6860 if (!p || !data || (*datalen < 1)) {
6861 errno = EINVAL;
6862 return -1;
6863 }
6864
6865 switch (option) {
6866 case AST_OPTION_TDD:
6867 cp = (char *) data;
6868 if (p->mate) {
6869 *cp = 2;
6870 } else {
6871 *cp = p->tdd ? 1 : 0;
6872 }
6873 break;
6875 cp = (char *) data;
6876 *cp = p->ignoredtmf ? 0 : 1;
6877 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6878 break;
6880 cp = (char *) data;
6881 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
6882 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6883 break;
6885#if defined(HAVE_PRI)
6886#if defined(HAVE_PRI_CCSS)
6888 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
6889 break;
6890 }
6891#endif /* defined(HAVE_PRI_CCSS) */
6892#endif /* defined(HAVE_PRI) */
6893 return -1;
6894 default:
6895 return -1;
6896 }
6897
6898 errno = 0;
6899
6900 return 0;
6901}
#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 3799 of file chan_dahdi.c.

3800{
3801 for (;;) {
3802 if (p->owner) {
3803 if (ast_channel_trylock(p->owner)) {
3805 } else {
3806 ast_queue_frame(p->owner, f);
3808 break;
3809 }
3810 } else
3811 break;
3812 }
3813}
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:1170

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

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

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

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

16050{
16051 switch (cmd) {
16052 case CLI_INIT:
16053 e->command = "dahdi restart";
16054 e->usage =
16055 "Usage: dahdi restart\n"
16056 " Restarts the DAHDI channels: destroys them all and then\n"
16057 " re-reads them from chan_dahdi.conf.\n"
16058 " Note that this will STOP any running CALL on DAHDI channels.\n"
16059 "";
16060 return NULL;
16061 case CLI_GENERATE:
16062 return NULL;
16063 }
16064 if (a->argc != 2)
16065 return CLI_SHOWUSAGE;
16066
16067 if (dahdi_restart() != 0)
16068 return CLI_FAILURE;
16069 return CLI_SUCCESS;
16070}

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

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

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

20612{
20613#define END_SILENCE_LEN 400
20614#define HEADER_MS 50
20615#define TRAILER_MS 5
20616#define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
20617#define ASCII_BYTES_PER_CHAR 80
20618
20619 unsigned char *buf,*mybuf;
20620 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
20621 struct pollfd fds[1];
20622 int size,res,fd,len,x;
20623 int bytes=0;
20624 int idx;
20625
20626 /*
20627 * Initial carrier (imaginary)
20628 *
20629 * Note: The following float variables are used by the
20630 * PUT_CLID_MARKMS and PUT_CLID() macros.
20631 */
20632 float cr = 1.0;
20633 float ci = 0.0;
20634 float scont = 0.0;
20635
20636 if (!text[0]) {
20637 return(0); /* if nothing to send, don't */
20638 }
20639 idx = dahdi_get_index(c, p, 0);
20640 if (idx < 0) {
20641 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
20642 return -1;
20643 }
20644 if ((!p->tdd) && (!p->mate)) {
20645#if defined(HAVE_PRI)
20646#if defined(HAVE_PRI_DISPLAY_TEXT)
20647 ast_mutex_lock(&p->lock);
20649 sig_pri_sendtext(p->sig_pvt, text);
20650 }
20652#endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
20653#endif /* defined(HAVE_PRI) */
20654 return(0); /* if not in TDD mode, just return */
20655 }
20656 if (p->mate)
20658 else
20659 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
20660 if (!buf)
20661 return -1;
20662 mybuf = buf;
20663 if (p->mate) {
20664 /* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
20665 struct ast_format *codec = AST_LAW(p);
20666
20667 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
20669 }
20670 /* Put actual message */
20671 for (x = 0; text[x]; x++) {
20672 PUT_CLID(text[x]);
20673 }
20674 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
20676 }
20677 len = bytes;
20678 buf = mybuf;
20679 } else {
20680 len = tdd_generate(p->tdd, buf, text);
20681 if (len < 1) {
20682 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
20683 ast_free(mybuf);
20684 return -1;
20685 }
20686 }
20687 memset(buf + len, 0x7f, END_SILENCE_LEN);
20689 fd = p->subs[idx].dfd;
20690 while (len) {
20691 if (ast_check_hangup(c)) {
20692 ast_free(mybuf);
20693 return -1;
20694 }
20695 size = len;
20696 if (size > READ_SIZE)
20697 size = READ_SIZE;
20698 fds[0].fd = fd;
20699 fds[0].events = POLLOUT | POLLPRI;
20700 fds[0].revents = 0;
20701 res = poll(fds, 1, -1);
20702 if (!res) {
20703 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
20704 continue;
20705 }
20706 /* if got exception */
20707 if (fds[0].revents & POLLPRI) {
20708 ast_free(mybuf);
20709 return -1;
20710 }
20711 if (!(fds[0].revents & POLLOUT)) {
20712 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
20713 continue;
20714 }
20715 res = write(fd, buf, size);
20716 if (res != size) {
20717 if (res == -1) {
20718 ast_free(mybuf);
20719 return -1;
20720 }
20721 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
20722 break;
20723 }
20724 len -= size;
20725 buf += size;
20726 }
20727 ast_free(mybuf);
20728 return(0);
20729}
char * text
Definition: app_queue.c:1768
#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:445
struct ast_codec * codec
Pointer to the codec in use for this format.
Definition: format.c:47
#define TDD_BYTES_PER_CHAR
Definition: tdd.h:27
int tdd_generate(struct tdd_state *tdd, unsigned char *buf, const char *string)
Definition: tdd.c:296

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

◆ dahdi_set_dnd()

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

Definition at line 16688 of file chan_dahdi.c.

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

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

5233{
5234 int x, res;
5235
5236 x = hs;
5237 res = ioctl(fd, DAHDI_HOOK, &x);
5238
5239 if (res < 0) {
5240 if (errno == EINPROGRESS)
5241 return 0;
5242 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
5243 /* will expectedly fail if phone is off hook during operation, such as during a restart */
5244 }
5245
5246 return res;
5247}

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

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

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

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

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

4472{
4473 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
4474}

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

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

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

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

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

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

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

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

4702{
4703 static char buf[256];
4704 switch (sig) {
4705 case SIG_EM:
4706 return "E & M Immediate";
4707 case SIG_EMWINK:
4708 return "E & M Wink";
4709 case SIG_EM_E1:
4710 return "E & M E1";
4711 case SIG_FEATD:
4712 return "Feature Group D (DTMF)";
4713 case SIG_FEATDMF:
4714 return "Feature Group D (MF)";
4715 case SIG_FEATDMF_TA:
4716 return "Feature Group D (MF) Tandem Access";
4717 case SIG_FEATB:
4718 return "Feature Group B (MF)";
4719 case SIG_E911:
4720 return "E911 (MF)";
4721 case SIG_FGC_CAMA:
4722 return "FGC/CAMA (Dialpulse)";
4723 case SIG_FGC_CAMAMF:
4724 return "FGC/CAMA (MF)";
4725 case SIG_FXSLS:
4726 return "FXS Loopstart";
4727 case SIG_FXSGS:
4728 return "FXS Groundstart";
4729 case SIG_FXSKS:
4730 return "FXS Kewlstart";
4731 case SIG_FXOLS:
4732 return "FXO Loopstart";
4733 case SIG_FXOGS:
4734 return "FXO Groundstart";
4735 case SIG_FXOKS:
4736 return "FXO Kewlstart";
4737 case SIG_PRI:
4738 return "ISDN PRI";
4739 case SIG_BRI:
4740 return "ISDN BRI Point to Point";
4741 case SIG_BRI_PTMP:
4742 return "ISDN BRI Point to MultiPoint";
4743 case SIG_SS7:
4744 return "SS7";
4745 case SIG_MFCR2:
4746 return "MFC/R2";
4747 case SIG_SF:
4748 return "SF (Tone) Immediate";
4749 case SIG_SFWINK:
4750 return "SF (Tone) Wink";
4751 case SIG_SF_FEATD:
4752 return "SF (Tone) with Feature Group D (DTMF)";
4753 case SIG_SF_FEATDMF:
4754 return "SF (Tone) with Feature Group D (MF)";
4755 case SIG_SF_FEATB:
4756 return "SF (Tone) with Feature Group B (MF)";
4757 case 0:
4758 return "Pseudo";
4759 default:
4760 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
4761 return buf;
4762 }
4763}
#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 15906 of file chan_dahdi.c.

15907{
15908 struct dahdi_pvt *p;
15909retry:
15911 for (p = iflist; p; p = p->next) {
15912 ast_mutex_lock(&p->lock);
15913 if (p->owner && !p->restartpending) {
15914 if (ast_channel_trylock(p->owner)) {
15915 if (DEBUG_ATLEAST(3))
15916 ast_verbose("Avoiding deadlock\n");
15917 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15920 goto retry;
15921 }
15922 if (DEBUG_ATLEAST(3))
15923 ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15925 p->restartpending = 1;
15928 }
15930 }
15932}
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2428
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2204
#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 5003 of file chan_dahdi.c.

5004{
5005 int x;
5006 int res;
5007
5008 if (p && p->echocanon && p->echotraining) {
5009 x = p->echotraining;
5010 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
5011 if (res)
5012 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
5013 else
5014 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
5015 } else {
5016 ast_debug(1, "No echo training requested\n");
5017 }
5018}

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

913{
914 int i, j = 0;
915 i = DAHDI_IOMUX_SIGEVENT;
916 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
917 return -1;
918 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
919 return -1;
920 return j;
921}

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

9881{
9882 int j;
9883 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
9884 for (;;)
9885 {
9886 /* set bits of interest */
9887 j = DAHDI_IOMUX_SIGEVENT;
9888 /* wait for some happening */
9889 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
9890 /* exit loop if we have it */
9891 if (j & DAHDI_IOMUX_SIGEVENT) break;
9892 }
9893 /* get the event info */
9894 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
9895 return 0;
9896}

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

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

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.

◆ dahdichan_helper()

static int dahdichan_helper ( struct ast_channel chan,
char *  data,
const char *  value,
char *  buffer,
size_t  buflen 
)
static

Definition at line 16975 of file chan_dahdi.c.

16976{
16977 char *parse;
16978 struct dahdi_pvt *pvt;
16979 struct dahdi_params dahdip;
16980 int res;
16982 AST_APP_ARG(property);
16983 AST_APP_ARG(dahdichan);
16984 );
16985
16986 parse = ast_strdupa(data);
16988
16989 if (buflen > 0) {
16990 *buffer = '\0';
16991 }
16992
16993 if (!ast_strlen_zero(args.dahdichan)) {
16994 /* DAHDI channel number explicitly provided, find it. */
16995 int channo = atoi(args.dahdichan);
16996 pvt = find_channel(channo);
16997 if (!pvt) {
16998 ast_log(LOG_ERROR, "DAHDI channel %d does not exist\n", channo);
16999 return -1;
17000 }
17001 } else {
17002 /* No channel specified explicitly, so implicitly use the current channel, in which case it must be a DAHDI channel. */
17003 if (!chan || !ast_channel_tech(chan) || strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
17004 ast_log(LOG_WARNING, "%s is not a DAHDI channel, and no DAHDI channel specified\n", ast_channel_name(chan));
17005 return -1;
17006 }
17007 pvt = ast_channel_tech_pvt(chan);
17008 }
17009
17010 memset(&dahdip, 0, sizeof(dahdip));
17011 if (ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &dahdip)) {
17012 ast_log(LOG_WARNING, "Unable to get parameters of DAHDI channel %d: %s\n", pvt->channel, strerror(errno));
17013 return -1;
17014 }
17015
17016 /* We have the channel private to use. */
17017 ast_mutex_lock(&pvt->lock);
17018 if (value) {
17019 res = dahdichan_write_property(pvt, &dahdip, args.property, value);
17020 } else {
17021 res = dahdichan_read_property(pvt, &dahdip, args.property, buffer, buflen);
17022 }
17023 ast_mutex_unlock(&pvt->lock);
17024 return res;
17025}
static int dahdichan_read_property(struct dahdi_pvt *p, struct dahdi_params *dahdip, const char *property, char *buffer, size_t len)
Definition: chan_dahdi.c:16900
static int dahdichan_write_property(struct dahdi_pvt *p, struct dahdi_params *dahdip, const char *property, const char *value)
Definition: chan_dahdi.c:16931
static struct dahdi_pvt * find_channel(int channel)
Definition: chan_dahdi.c:16848
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.

References args, AST_APP_ARG, ast_channel_name(), ast_channel_tech(), ast_channel_tech_pvt(), AST_DECLARE_APP_ARGS, ast_log, ast_mutex_lock, ast_mutex_unlock, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), dahdi_pvt::channel, dahdichan_read_property(), dahdichan_write_property(), dahdi_subchannel::dfd, errno, find_channel(), dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, SUB_REAL, dahdi_pvt::subs, type, and value.

Referenced by dahdichan_read(), and dahdichan_write().

◆ dahdichan_read()

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

Definition at line 17027 of file chan_dahdi.c.

17028{
17029 return dahdichan_helper(chan, data, NULL, buffer, buflen);
17030}
static int dahdichan_helper(struct ast_channel *chan, char *data, const char *value, char *buffer, size_t buflen)
Definition: chan_dahdi.c:16975

References dahdichan_helper(), and NULL.

◆ dahdichan_read_property()

static int dahdichan_read_property ( struct dahdi_pvt p,
struct dahdi_params *  dahdip,
const char *  property,
char *  buffer,
size_t  len 
)
static

Definition at line 16900 of file chan_dahdi.c.

16901{
16902 struct analog_pvt *analog_p = p->sig_pvt;
16903
16904 /* R/O properties */
16905 if (!strcasecmp(property, "owner")) {
16906 return print_subchannel(p, SUB_REAL, buffer, len);
16907 } else if (!strcasecmp(property, "callwait")) {
16908 return print_subchannel(p, SUB_CALLWAIT, buffer, len);
16909 } else if (!strcasecmp(property, "threeway")) {
16910 return print_subchannel(p, SUB_THREEWAY, buffer, len);
16911 /* R/W properties */
16912 } else if (!strcasecmp(property, "polarity")) {
16914 snprintf(buffer, len, "%d", p->polarity);
16915 } else if (!strcasecmp(property, "dnd")) {
16917 snprintf(buffer, len, "%d", analog_p->dnd);
16918 } else if (!strcasecmp(property, "callforward")) {
16920 snprintf(buffer, len, "%s", analog_p->call_forward);
16921 } else if (!strcasecmp(property, "lastexten")) {
16923 snprintf(buffer, len, "%s", analog_p->lastexten);
16924 } else {
16925 ast_log(LOG_ERROR, "Unknown DAHDI_CHANNEL property '%s'\n", property);
16926 return -1;
16927 }
16928 return 0;
16929}
#define REQUIRE_FXO_SIG()
Definition: chan_dahdi.c:16894
static int print_subchannel(struct dahdi_pvt *p, int subchan, char *buffer, size_t len)
Definition: chan_dahdi.c:16883
unsigned int dnd
Definition: sig_analog.h:340
char lastexten[AST_MAX_EXTENSION]
Definition: sig_analog.h:364
char call_forward[AST_MAX_EXTENSION]
Definition: sig_analog.h:379

References ast_log, analog_pvt::call_forward, analog_pvt::dnd, analog_pvt::lastexten, len(), LOG_ERROR, dahdi_pvt::polarity, print_subchannel(), REQUIRE_FXO_SIG, dahdi_pvt::sig_pvt, SUB_CALLWAIT, SUB_REAL, and SUB_THREEWAY.

Referenced by dahdichan_helper(), and polarity_read().

◆ dahdichan_write()

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

Definition at line 17032 of file chan_dahdi.c.

17033{
17034 return dahdichan_helper(chan, data, value, NULL, 0);
17035}

References dahdichan_helper(), NULL, and value.

◆ dahdichan_write_property()

static int dahdichan_write_property ( struct dahdi_pvt p,
struct dahdi_params *  dahdip,
const char *  property,
const char *  value 
)
static

Definition at line 16931 of file chan_dahdi.c.

16932{
16933 struct analog_pvt *analog_p = p->sig_pvt;
16934
16935 /* We don't need to check ast_strlen_zero(value) because it's obviously not NULL.
16936 * It may even be okay for it to be an empty string, but that's a per-setting thing. */
16937
16938 /* R/O properties */
16939 if (!strcasecmp(property, "owner") || !strcasecmp(property, "callwait") || !strcasecmp(property, "threeway")) {
16940 ast_log(LOG_ERROR, "DAHDI subchannel names are R/O\n");
16941 return -1;
16942 /* R/W properties */
16943 } else if (!strcasecmp(property, "polarity")) {
16944 int polarity = atoi(value);
16947 ast_log(LOG_ERROR, "Invalid polarity: '%s'\n", value);
16948 return -1;
16949 }
16951 } else if (!strcasecmp(property, "dnd")) {
16952 int dnd = atoi(value);
16954 analog_dnd(analog_p, dnd ? 1 : 0);
16955 } else if (!strcasecmp(property, "callforward")) {
16957 if (strlen(value) >= sizeof(analog_p->call_forward) - 1) {
16958 ast_log(LOG_ERROR, "Provided call forwarding target '%s' is too long\n", value);
16959 }
16960 ast_copy_string(analog_p->call_forward, value, sizeof(analog_p->call_forward)); /* Could be empty to clear value */
16961 } else if (!strcasecmp(property, "lastexten")) {
16963 if (strlen(value) >= sizeof(analog_p->lastexten) - 1) {
16964 ast_log(LOG_ERROR, "Provided lastexten target '%s' is too long\n", value);
16965 }
16966 ast_copy_string(analog_p->lastexten, value, sizeof(analog_p->lastexten)); /* Could be empty to clear value */
16967 } else {
16968 ast_log(LOG_ERROR, "Unknown DAHDI_CHANNEL property '%s'\n", property);
16969 return -1;
16970 }
16971 return 0;
16972}
static void my_set_polarity(void *pvt, int value)
Definition: chan_dahdi.c:2925
int polarity
Definition: sig_analog.h:370

References analog_dnd(), ast_copy_string(), ast_log, analog_pvt::call_forward, analog_pvt::dnd, analog_pvt::lastexten, LOG_ERROR, my_set_polarity(), analog_pvt::polarity, POLARITY_IDLE, POLARITY_REV, REQUIRE_FXO_SIG, dahdi_pvt::sig_pvt, and value.

Referenced by dahdichan_helper(), and polarity_write().

◆ dahdichannel_to_ami()

static struct ast_manager_event_blob * dahdichannel_to_ami ( struct stasis_message msg)
static

Definition at line 2040 of file chan_dahdi.c.

2041{
2042 RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
2043 struct ast_channel_blob *obj = stasis_message_data(msg);
2044 struct ast_json *group, *span, *channel;
2045
2046 channel_string = ast_manager_build_channel_state_string(obj->snapshot);
2047 if (!channel_string) {
2048 return NULL;
2049 }
2050
2051 group = ast_json_object_get(obj->blob, "group");
2052 span = ast_json_object_get(obj->blob, "span");
2053 channel = ast_json_object_get(obj->blob, "channel");
2054
2055 return ast_manager_event_blob_create(EVENT_FLAG_CALL, "DAHDIChannel",
2056 "%s"
2057 "DAHDIGroup: %llu\r\n"
2058 "DAHDISpan: %u\r\n"
2059 "DAHDIChannel: %s\r\n",
2060 ast_str_buffer(channel_string),
2062 (unsigned int)ast_json_integer_get(span),
2063 ast_json_string_get(channel));
2064}
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:10144
#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 2736 of file chan_dahdi.c.

2737{
2738 enum analog_event res;
2739
2740 switch (event) {
2741 case DAHDI_EVENT_ONHOOK:
2742 res = ANALOG_EVENT_ONHOOK;
2743 break;
2744 case DAHDI_EVENT_RINGOFFHOOK:
2746 break;
2747 case DAHDI_EVENT_WINKFLASH:
2749 break;
2750 case DAHDI_EVENT_ALARM:
2751 res = ANALOG_EVENT_ALARM;
2752 break;
2753 case DAHDI_EVENT_NOALARM:
2755 break;
2756 case DAHDI_EVENT_DIALCOMPLETE:
2758 break;
2759 case DAHDI_EVENT_RINGERON:
2761 break;
2762 case DAHDI_EVENT_RINGEROFF:
2764 break;
2765 case DAHDI_EVENT_HOOKCOMPLETE:
2767 break;
2768 case DAHDI_EVENT_PULSE_START:
2770 break;
2771 case DAHDI_EVENT_POLARITY:
2773 break;
2774 case DAHDI_EVENT_RINGBEGIN:
2776 break;
2777 case DAHDI_EVENT_EC_DISABLED:
2779 break;
2780 case DAHDI_EVENT_REMOVED:
2782 break;
2783 case DAHDI_EVENT_NEONMWI_ACTIVE:
2785 break;
2786 case DAHDI_EVENT_NEONMWI_INACTIVE:
2788 break;
2789#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
2790 case DAHDI_EVENT_TX_CED_DETECTED:
2792 break;
2793 case DAHDI_EVENT_RX_CED_DETECTED:
2795 break;
2796 case DAHDI_EVENT_EC_NLP_DISABLED:
2798 break;
2799 case DAHDI_EVENT_EC_NLP_ENABLED:
2801 break;
2802#endif
2803 case DAHDI_EVENT_PULSEDIGIT:
2805 break;
2806 case DAHDI_EVENT_DTMFDOWN:
2808 break;
2809 case DAHDI_EVENT_DTMFUP:
2810 res = ANALOG_EVENT_DTMFUP;
2811 break;
2812 default:
2813 switch(event & 0xFFFF0000) {
2814 case DAHDI_EVENT_PULSEDIGIT:
2815 case DAHDI_EVENT_DTMFDOWN:
2816 case DAHDI_EVENT_DTMFUP:
2817 /* The event includes a digit number in the low word.
2818 * Converting it to a 'enum analog_event' would remove
2819 * that information. Thus it is returned as-is.
2820 */
2821 return event;
2822 }
2823
2824 res = ANALOG_EVENT_ERROR;
2825 break;
2826 }
2827
2828 return res;
2829}
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 1312 of file chan_dahdi.c.

1313{
1314 switch (sig) {
1315 case SIG_FXOLS:
1316 return ANALOG_SIG_FXOLS;
1317 case SIG_FXOGS:
1318 return ANALOG_SIG_FXOGS;
1319 case SIG_FXOKS:
1320 return ANALOG_SIG_FXOKS;
1321 case SIG_FXSLS:
1322 return ANALOG_SIG_FXSLS;
1323 case SIG_FXSGS:
1324 return ANALOG_SIG_FXSGS;
1325 case SIG_FXSKS:
1326 return ANALOG_SIG_FXSKS;
1327 case SIG_EMWINK:
1328 return ANALOG_SIG_EMWINK;
1329 case SIG_EM:
1330 return ANALOG_SIG_EM;
1331 case SIG_EM_E1:
1332 return ANALOG_SIG_EM_E1;
1333 case SIG_FEATD:
1334 return ANALOG_SIG_FEATD;
1335 case SIG_FEATDMF:
1336 return ANALOG_SIG_FEATDMF;
1337 case SIG_E911:
1338 return SIG_E911;
1339 case SIG_FGC_CAMA:
1340 return ANALOG_SIG_FGC_CAMA;
1341 case SIG_FGC_CAMAMF:
1342 return ANALOG_SIG_FGC_CAMAMF;
1343 case SIG_FEATB:
1344 return ANALOG_SIG_FEATB;
1345 case SIG_SFWINK:
1346 return ANALOG_SIG_SFWINK;
1347 case SIG_SF:
1348 return ANALOG_SIG_SF;
1349 case SIG_SF_FEATD:
1350 return ANALOG_SIG_SF_FEATD;
1351 case SIG_SF_FEATDMF:
1352 return ANALOG_SIG_SF_FEATDMF;
1353 case SIG_FEATDMF_TA:
1354 return ANALOG_SIG_FEATDMF_TA;
1355 case SIG_SF_FEATB:
1356 return ANALOG_SIG_FEATB;
1357 default:
1358 return -1;
1359 }
1360}
@ 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 20219 of file chan_dahdi.c.

20220{
20221 struct ast_cc_config_params *cc_params;
20222
20223 cc_params = dest->chan.cc_params;
20224 *dest = *src;
20225 dest->chan.cc_params = cc_params;
20227}

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

5976{
5977 int chan;
5978#if defined(HAVE_PRI)
5979 unsigned span;
5980 struct sig_pri_span *pri;
5981#endif /* defined(HAVE_PRI) */
5982 struct dahdi_pvt *p;
5983
5984 while (num_restart_pending) {
5985 usleep(1);
5986 }
5987
5989 /* Destroy all the interfaces and free their memory */
5990 while (iflist) {
5991 p = iflist;
5992
5993 chan = p->channel;
5994#if defined(HAVE_PRI_SERVICE_MESSAGES)
5995 {
5996 char db_chan_name[20];
5997 char db_answer[5];
5998 char state;
5999 int why = -1;
6000
6001 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
6002 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
6003 sscanf(db_answer, "%1c:%30d", &state, &why);
6004 }
6005 if (!why) {
6006 /* SRVST persistence is not required */
6007 ast_db_del(db_chan_name, SRVST_DBKEY);
6008 }
6009 }
6010#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
6011 /* Free associated memory */
6013 ast_verb(3, "Unregistered channel %d\n", chan);
6014 }
6015 ifcount = 0;
6017
6018#if defined(HAVE_PRI)
6019 /* Destroy all of the no B channel interface lists */
6020 for (span = 0; span < NUM_SPANS; ++span) {
6021 if (!pris[span].dchannels[0]) {
6022 break;
6023 }
6024 pri = &pris[span].pri;
6025 ast_mutex_lock(&pri->lock);
6026 while (pri->no_b_chan_iflist) {
6027 p = pri->no_b_chan_iflist;
6028
6029 /* Free associated memory */
6031 }
6032 ast_mutex_unlock(&pri->lock);
6033 }
6034#endif /* defined(HAVE_PRI) */
6035}
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:5877
static int ifcount
Definition: chan_dahdi.c:879
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 5957 of file chan_dahdi.c.

5958{
5959 int i;
5960
5961 if (!now) {
5962 /* Do not destroy the channel now if it is owned by someone. */
5963 if (cur->owner) {
5964 return;
5965 }
5966 for (i = 0; i < 3; i++) {
5967 if (cur->subs[i].owner) {
5968 return;
5969 }
5970 }
5971 }
5972 destroy_dahdi_pvt(cur);
5973}

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

5878{
5879 struct dahdi_pvt *p = pvt;
5880
5881 if (p->manages_span_alarms) {
5883 if (next) {
5885 }
5886 }
5887
5888 /* Remove channel from the list */
5889#if defined(HAVE_PRI)
5890 dahdi_unlink_pri_pvt(p);
5891#endif /* defined(HAVE_PRI) */
5892#if defined(HAVE_SS7)
5893 dahdi_unlink_ss7_pvt(p);
5894#endif /* defined(HAVE_SS7) */
5895#if defined(HAVE_OPENR2)
5896 dahdi_unlink_mfcr2_pvt(p);
5897#endif /* defined(HAVE_SS7) */
5898 switch (pvt->which_iflist) {
5899 case DAHDI_IFLIST_NONE:
5900 break;
5901 case DAHDI_IFLIST_MAIN:
5903 break;
5904#if defined(HAVE_PRI)
5905 case DAHDI_IFLIST_NO_B_CHAN:
5906 if (p->pri) {
5907 dahdi_nobch_extract(p->pri, p);
5908 }
5909 break;
5910#endif /* defined(HAVE_PRI) */
5911 }
5912
5913 if (p->sig_pvt) {
5914 if (dahdi_analog_lib_handles(p->sig, 0, 0)) {
5916 }
5917 switch (p->sig) {
5918#if defined(HAVE_PRI)
5921 break;
5922#endif /* defined(HAVE_PRI) */
5923#if defined(HAVE_SS7)
5924 case SIG_SS7:
5926 break;
5927#endif /* defined(HAVE_SS7) */
5928 default:
5929 break;
5930 }
5931 }
5932 ast_free(p->cidspill);
5933 if (p->use_smdi) {
5935 }
5936 if (p->mwi_event_sub) {
5938 }
5939 if (p->vars) {
5941 }
5942 if (p->cc_params) {
5944 }
5945
5948
5951 if (p->owner) {
5953 }
5954 ast_free(p);
5955}
static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5650
static struct dahdi_pvt * find_next_iface_in_span(struct dahdi_pvt *cur)
Definition: chan_dahdi.c:5866
struct ast_namedgroups * ast_unref_namedgroups(struct ast_namedgroups *groups)
Definition: channel.c:7714
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1260
#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:4392
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 13835 of file chan_dahdi.c.

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

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

4532{
4533 if (isdigit(digit))
4534 return DAHDI_TONE_DTMF_BASE + (digit - '0');
4535 else if (digit >= 'A' && digit <= 'D')
4536 return DAHDI_TONE_DTMF_A + (digit - 'A');
4537 else if (digit >= 'a' && digit <= 'd')
4538 return DAHDI_TONE_DTMF_A + (digit - 'a');
4539 else if (digit == '*')
4540 return DAHDI_TONE_DTMF_s;
4541 else if (digit == '#')
4542 return DAHDI_TONE_DTMF_p;
4543 else
4544 return -1;
4545}

References digit.

Referenced by dahdi_digit_begin().

◆ do_monitor()

static void * do_monitor ( void *  data)
static

Definition at line 11943 of file chan_dahdi.c.

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

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

5049{
5050 float neg;
5051 float shallow, steep;
5052 float max = SHRT_MAX;
5053
5054 neg = (sample < 0 ? -1 : 1);
5055 steep = drc*sample;
5056 shallow = neg*(max-max/drc)+(float)sample/drc;
5057 if (fabsf(steep) < fabsf(shallow)) {
5058 sample = steep;
5059 }
5060 else {
5061 sample = shallow;
5062 }
5063
5064 return sample;
5065}
#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 13771 of file chan_dahdi.c.

13772{
13773 struct dahdi_pvt *p;
13774 struct dahdi_bufferinfo bi;
13775 int res;
13776
13777 p = ast_malloc(sizeof(*p));
13778 if (!p) {
13779 return NULL;
13780 }
13781 *p = *src;
13782
13783 /* Must deep copy the cc_params. */
13785 if (!p->cc_params) {
13786 ast_free(p);
13787 return NULL;
13788 }
13790
13792 p->next = NULL;
13793 p->prev = NULL;
13794 ast_mutex_init(&p->lock);
13795 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13796 if (p->subs[SUB_REAL].dfd < 0) {
13797 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13799 return NULL;
13800 }
13801 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13802 if (!res) {
13803 bi.txbufpolicy = src->buf_policy;
13804 bi.rxbufpolicy = src->buf_policy;
13805 bi.numbufs = src->buf_no;
13806 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13807 if (res < 0) {
13808 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13809 }
13810 } else
13811 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13812 p->destroy = 1;
13814 return p;
13815}
static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5602
#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 4692 of file chan_dahdi.c.

4693{
4694 static char buf[256];
4695 if ((event > -1) && (event < (ARRAY_LEN(events))) )
4696 return events[event];
4697 sprintf(buf, "Event %d", event); /* safe */
4698 return buf;
4699}
static const char *const events[]
Definition: chan_dahdi.c:4647

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

5119{
5120 int j;
5121 int k;
5122 float linear_gain = pow(10.0, gain / 20.0);
5123
5124 switch (law) {
5125 case DAHDI_LAW_ALAW:
5126 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5127 if (gain || drc) {
5128 k = AST_ALAW(j);
5129 if (drc) {
5130 k = drc_sample(k, drc);
5131 }
5132 k = (float)k * linear_gain;
5133 if (k > 32767) {
5134 k = 32767;
5135 } else if (k < -32768) {
5136 k = -32768;
5137 }
5138 g->rxgain[j] = AST_LIN2A(k);
5139 } else {
5140 g->rxgain[j] = j;
5141 }
5142 }
5143 break;
5144 case DAHDI_LAW_MULAW:
5145 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5146 if (gain || drc) {
5147 k = AST_MULAW(j);
5148 if (drc) {
5149 k = drc_sample(k, drc);
5150 }
5151 k = (float)k * linear_gain;
5152 if (k > 32767) {
5153 k = 32767;
5154 } else if (k < -32768) {
5155 k = -32768;
5156 }
5157 g->rxgain[j] = AST_LIN2MU(k);
5158 } else {
5159 g->rxgain[j] = j;
5160 }
5161 }
5162 break;
5163 }
5164}
#define AST_LIN2A(a)
Definition: alaw.h:50
static int drc_sample(int sample, float drc)
Definition: chan_dahdi.c:5048
#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 5068 of file chan_dahdi.c.

5069{
5070 int j;
5071 int k;
5072
5073 float linear_gain = pow(10.0, gain / 20.0);
5074
5075 switch (law) {
5076 case DAHDI_LAW_ALAW:
5077 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
5078 if (gain || drc) {
5079 k = AST_ALAW(j);
5080 if (drc) {
5081 k = drc_sample(k, drc);
5082 }
5083 k = (float)k * linear_gain;
5084 if (k > 32767) {
5085 k = 32767;
5086 } else if (k < -32768) {
5087 k = -32768;
5088 }
5089 g->txgain[j] = AST_LIN2A(k);
5090 } else {
5091 g->txgain[j] = j;
5092 }
5093 }
5094 break;
5095 case DAHDI_LAW_MULAW:
5096 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
5097 if (gain || drc) {
5098 k = AST_MULAW(j);
5099 if (drc) {
5100 k = drc_sample(k, drc);
5101 }
5102 k = (float)k * linear_gain;
5103 if (k > 32767) {
5104 k = 32767;
5105 } else if (k < -32768) {
5106 k = -32768;
5107 }
5108 g->txgain[j] = AST_LIN2MU(k);
5109
5110 } else {
5111 g->txgain[j] = j;
5112 }
5113 }
5114 break;
5115 }
5116}

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

16849{
16850 struct dahdi_pvt *p;
16851
16853 for (p = iflist; p; p = p->next) {
16854 if (p->channel == channel) {
16855 break;
16856 }
16857 }
16859 return p;
16860}

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

Referenced by dahdichan_helper(), and find_channel_from_str().

◆ find_channel_from_str()

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

Definition at line 16871 of file chan_dahdi.c.

16872{
16873 int chan_num;
16874
16875 if (sscanf(channel, "%30d", &chan_num) != 1) {
16876 /* Not numeric string. */
16877 return NULL;
16878 }
16879
16880 return find_channel(chan_num);
16881}

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

5867{
5868 if (cur->next && cur->next->span == cur->span) {
5869 return cur->next;
5870 } else if (cur->prev && cur->prev->span == cur->span) {
5871 return cur->prev;
5872 }
5873
5874 return NULL;
5875}

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

Referenced by destroy_dahdi_pvt().

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

7628{
7629 int res;
7630 struct dahdi_spaninfo zi;
7631 struct dahdi_params params;
7632
7633 memset(&zi, 0, sizeof(zi));
7634 zi.spanno = p->span;
7635
7636 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
7637 if (zi.alarms != DAHDI_ALARM_NONE)
7638 return zi.alarms;
7639 } else {
7640 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
7641 return 0;
7642 }
7643
7644 /* No alarms on the span. Check for channel alarms. */
7645 memset(&params, 0, sizeof(params));
7646 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
7647 return params.chan_alarms;
7648
7649 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
7650
7651 return DAHDI_ALARM_NONE;
7652}

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

7788{
7789 const char *alarm_str;
7790
7791#if defined(HAVE_PRI)
7793 return;
7794 }
7795#endif /* defined(HAVE_PRI) */
7796
7797 alarm_str = alarm2str(alms);
7799 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
7800 publish_channel_alarm(p->channel, alarm_str);
7801 }
7802
7804 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
7805 publish_span_alarm(p->span, alarm_str);
7806 }
7807}
static void publish_channel_alarm(int channel, const char *alarm_txt)
Definition: chan_dahdi.c:7768
static void publish_span_alarm(int span, const char *alarm_txt)
Definition: chan_dahdi.c:7754
static int report_alarms
Definition: chan_dahdi.c:868
#define REPORT_CHANNEL_ALARMS
Definition: chan_dahdi.c:866
#define REPORT_SPAN_ALARMS
Definition: chan_dahdi.c:867
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 3846 of file chan_dahdi.c.

3847{
3848#if defined(HAVE_PRI)
3850 return;
3851 }
3852#endif /* defined(HAVE_PRI) */
3853
3856 }
3859 }
3860}
static void publish_channel_alarm_clear(int channel)
Definition: chan_dahdi.c:3815
static void publish_span_alarm_clear(int span)
Definition: chan_dahdi.c:3833

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

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

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

5344{
5345 int new_msgs;
5346 RAII_VAR(struct stasis_message *, mwi_message, NULL, ao2_cleanup);
5347
5348 /* A manual MWI disposition has been requested, use that instead
5349 * if this is for sending the new MWI indication. */
5350 if (p->mwioverride_active) {
5351 /* We don't clear p->mwioverride_active automatically,
5352 * because otherwise do_monitor would just change it back to the way it was.
5353 * We need to keep the override active until explicitly disabled by the user,
5354 * so that we can keep returning the correct answer in subsequent calls to do_monitor. */
5355 ast_debug(6, "MWI manual override active on channel %d: pretending that it should be %s\n",
5356 p->channel, p->mwioverride_disposition ? "active" : "inactive");
5357 return p->mwioverride_disposition;
5358 }
5359
5361 if (mwi_message) {
5362 struct ast_mwi_state *mwi_state = stasis_message_data(mwi_message);
5363 new_msgs = mwi_state->new_msgs;
5364 } else {
5366 }
5367
5368 return new_msgs;
5369}
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 13532 of file chan_dahdi.c.

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

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

4806{
4807 /* If they're listening to our channel, they're ours */
4808 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
4809 return 1;
4810 /* If they're a talker on our (allocated) conference, they're ours */
4811 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
4812 return 1;
4813 return 0;
4814}

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

4836{
4837 int x;
4838 int useslavenative;
4839 struct dahdi_pvt *slave = NULL;
4840 /* Start out optimistic */
4841 useslavenative = 1;
4842 /* Update conference state in a stateless fashion */
4843 for (x = 0; x < 3; x++) {
4844 /* Any three-way calling makes slave native mode *definitely* out
4845 of the question */
4846 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
4847 useslavenative = 0;
4848 }
4849 /* If we don't have any 3-way calls, check to see if we have
4850 precisely one slave */
4851 if (useslavenative) {
4852 for (x = 0; x < MAX_SLAVES; x++) {
4853 if (p->slaves[x]) {
4854 if (slave) {
4855 /* Whoops already have a slave! No
4856 slave native and stop right away */
4857 slave = NULL;
4858 useslavenative = 0;
4859 break;
4860 } else {
4861 /* We have one slave so far */
4862 slave = p->slaves[x];
4863 }
4864 }
4865 }
4866 }
4867 /* If no slave, slave native definitely out */
4868 if (!slave)
4869 useslavenative = 0;
4870 else if (slave->law != p->law) {
4871 useslavenative = 0;
4872 slave = NULL;
4873 }
4874 if (out)
4875 *out = slave;
4876 return useslavenative;
4877}

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

20502{
20503 int res;
20504#if defined(HAVE_PRI) || defined(HAVE_SS7)
20505 int y;
20506#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
20507
20508 if (STASIS_MESSAGE_TYPE_INIT(dahdichannel_type)) {
20510 }
20511
20514 }
20518
20522 }
20523
20524#ifdef HAVE_PRI
20525 memset(pris, 0, sizeof(pris));
20526 for (y = 0; y < NUM_SPANS; y++) {
20527 sig_pri_init_pri(&pris[y].pri);
20528 }
20529 pri_set_error(dahdi_pri_error);
20530 pri_set_message(dahdi_pri_message);
20531 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
20532#ifdef HAVE_PRI_PROG_W_CAUSE
20533 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
20534#endif
20535#if defined(HAVE_PRI_CCSS)
20536 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
20537 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
20540 }
20541#endif /* defined(HAVE_PRI_CCSS) */
20542 if (sig_pri_load(
20543#if defined(HAVE_PRI_CCSS)
20544 dahdi_pri_cc_type
20545#else
20546 NULL
20547#endif /* defined(HAVE_PRI_CCSS) */
20548 )) {
20551 }
20552#endif
20553#if defined(HAVE_SS7)
20554 memset(linksets, 0, sizeof(linksets));
20555 for (y = 0; y < NUM_SPANS; y++) {
20556 sig_ss7_init_linkset(&linksets[y].ss7);
20557 }
20558 ss7_set_error(dahdi_ss7_error);
20559 ss7_set_message(dahdi_ss7_message);
20560 ss7_set_hangup(sig_ss7_cb_hangup);
20561 ss7_set_notinservice(sig_ss7_cb_notinservice);
20562 ss7_set_call_null(sig_ss7_cb_call_null);
20563#endif /* defined(HAVE_SS7) */
20564 res = setup_dahdi(0);
20565 /* Make sure we can register our DAHDI channel type */
20566 if (res) {
20569 }
20571 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
20574 }
20575#ifdef HAVE_PRI
20576 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
20577#endif
20578#if defined(HAVE_SS7)
20579 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
20580#endif /* defined(HAVE_SS7) */
20581#ifdef HAVE_OPENR2
20582 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
20583 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
20584#endif
20585
20588
20590 memset(round_robin, 0, sizeof(round_robin));
20591 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
20593 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
20596 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
20597 ast_manager_register_xml("DAHDIShowStatus", 0, action_dahdishowstatus);
20599#if defined(HAVE_PRI)
20600 ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
20601 ast_manager_register_xml("PRIDebugSet", 0, action_pri_debug_set);
20602 ast_manager_register_xml("PRIDebugFileSet", EVENT_FLAG_SYSTEM, action_pri_debug_file_set);
20603 ast_manager_register_xml("PRIDebugFileUnset", 0, action_pri_debug_file_unset);
20604#endif /* defined(HAVE_PRI) */
20605
20607
20608 return res;
20609}
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:18401
static int action_transfer(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:17121
static int action_dahdidndon(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:17083
static int action_dahdishowchannels(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:17199
static int action_dahdirestart(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16072
static int action_dahdidndoff(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:17102
static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:17167
static int action_transferhangup(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:17144
static int action_dahdishowstatus(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:17287
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:539
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define ast_cond_init(cond, attr)
Definition: lock.h: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:1562
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, dahdichan_function, 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 12582 of file chan_dahdi.c.

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

11938 {
11939 struct pollfd **pfds = arg;
11940 ast_free(*pfds);
11941}

References ast_free.

Referenced by do_monitor().

◆ mwi_send_init()

static int mwi_send_init ( struct dahdi_pvt pvt)
static

Definition at line 11344 of file chan_dahdi.c.

11345{
11346 int x;
11347
11348#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11349 /* Determine how this spill is to be sent */
11350 if (pvt->mwisend_rpas) {
11352 pvt->mwisendactive = 1;
11353 } else if (pvt->mwisend_fsk) {
11355 pvt->mwisendactive = 1;
11356 } else {
11357 pvt->mwisendactive = 0;
11358 return 0;
11359 }
11360#else
11361 if (mwisend_rpas) {
11363 } else {
11365 }
11366 pvt->mwisendactive = 1;
11367#endif
11368
11369 if (pvt->cidspill) {
11370 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11371 ast_free(pvt->cidspill);
11372 pvt->cidspill = NULL;
11373 pvt->cidpos = 0;
11374 pvt->cidlen = 0;
11375 }
11377 if (!pvt->cidspill) {
11378 pvt->mwisendactive = 0;
11379 return -1;
11380 }
11381 x = DAHDI_FLUSH_BOTH;
11382 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11383 x = 3000;
11384 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11385#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11386 if (pvt->mwisend_fsk) {
11387#endif
11389 CID_MWI_TYPE_MDMF_FULL, AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11390 pvt->cidpos = 0;
11391#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11392 }
11393#endif
11394 return 0;
11395}
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:853
@ 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 11397 of file chan_dahdi.c.

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

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

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

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

2394{
2395 struct dahdi_pvt *p = pvt;
2396 int res, law;
2397
2398 p->faxhandled = 0;
2399 p->didtdd = 0;
2400
2401 if (p->dsp) {
2402 ast_dsp_free(p->dsp);
2403 p->dsp = NULL;
2404 }
2405
2406 p->law = p->law_default;
2407 law = p->law_default;
2408 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2409 if (res < 0)
2410 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2411
2413
2414#if 1
2415 {
2416 int i;
2417 p->owner = NULL;
2418 /* Cleanup owners here */
2419 for (i = 0; i < 3; i++) {
2420 p->subs[i].owner = NULL;
2421 }
2422 }
2423#endif
2424
2425 reset_conf(p);
2426 if (num_restart_pending == 0) {
2428 }
2429}

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

2711{
2712 struct dahdi_pvt *p = pvt;
2713
2714 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
2715}
static int analogsub_to_dahdisub(enum analog_sub analogsub)
Definition: chan_dahdi.c:1383

References alloc_sub(), and analogsub_to_dahdisub().

◆ my_answer_polarityswitch()

static void my_answer_polarityswitch ( void *  pvt)
static

Definition at line 2945 of file chan_dahdi.c.

2946{
2947 struct dahdi_pvt *p = pvt;
2948
2949 if (!p->answeronpolarityswitch) {
2950 return;
2951 }
2952
2953 my_set_polarity(pvt, 1);
2954}

References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().

◆ my_callwait()

static int my_callwait ( void *  pvt)
static

Definition at line 1794 of file chan_dahdi.c.

1795{
1796 struct dahdi_pvt *p = pvt;
1797
1799 if (p->cidspill) {
1800 ast_log(LOG_WARNING, "Spill already exists?!?\n");
1801 ast_free(p->cidspill);
1802 }
1803
1804 /*
1805 * SAS: Subscriber Alert Signal, 440Hz for 300ms
1806 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
1807 */
1808 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1809 return -1;
1810 save_conference(p);
1811 /* Silence */
1812 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1813 if (!p->callwaitrings && p->callwaitingcallerid) {
1814 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1815 p->callwaitcas = 1;
1816 p->cidlen = 2400 + 680 + READ_SIZE * 4;
1817 } else {
1818 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1819 p->callwaitcas = 0;
1820 p->cidlen = 2400 + READ_SIZE * 4;
1821 }
1822 p->cidpos = 0;
1823 send_callerid(p);
1824
1825 return 0;
1826}

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

2344{
2345 struct dahdi_pvt *p = pvt;
2346
2347 ast_free(p->cidspill);
2348 p->cidspill = NULL;
2350}

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

◆ my_check_confirmanswer()

static int my_check_confirmanswer ( void *  pvt)
static

Definition at line 2326 of file chan_dahdi.c.

2327{
2328 struct dahdi_pvt *p = pvt;
2329 if (p->confirmanswer) {
2330 return 1;
2331 }
2332
2333 return 0;
2334}

References dahdi_pvt::confirmanswer.

◆ my_check_for_conference()

static int my_check_for_conference ( void *  pvt)
static

Definition at line 2503 of file chan_dahdi.c.

2504{
2505 struct dahdi_pvt *p = pvt;
2506 return check_for_conference(p);
2507}

References check_for_conference().

◆ my_check_waitingfordt()

static int my_check_waitingfordt ( void *  pvt)
static

Definition at line 2309 of file chan_dahdi.c.

2310{
2311 struct dahdi_pvt *p = pvt;
2312
2313 if (p->waitingfordt.tv_sec) {
2314 return 1;
2315 }
2316
2317 return 0;
2318}

References dahdi_pvt::waitingfordt.

◆ my_complete_conference_update()

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

Definition at line 2453 of file chan_dahdi.c.

2454{
2455 struct dahdi_pvt *p = pvt;
2456 int needconf = needconference;
2457 int x;
2458 int useslavenative;
2459 struct dahdi_pvt *slave = NULL;
2460
2461 useslavenative = isslavenative(p, &slave);
2462
2463 /* If we have a slave, add him to our conference now. or DAX
2464 if this is slave native */
2465 for (x = 0; x < MAX_SLAVES; x++) {
2466 if (p->slaves[x]) {
2467 if (useslavenative)
2468 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
2469 else {
2470 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
2471 needconf++;
2472 }
2473 }
2474 }
2475 /* If we're supposed to be in there, do so now */
2476 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
2477 if (useslavenative)
2478 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
2479 else {
2480 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
2481 needconf++;
2482 }
2483 }
2484 /* If we have a master, add ourselves to his conference */
2485 if (p->master) {
2486 if (isslavenative(p->master, NULL)) {
2488 } else {
2489 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
2490 }
2491 }
2492 if (!needconf) {
2493 /* Nobody is left (or should be left) in our conference.
2494 Kill it. */
2495 p->confno = -1;
2496 }
2497
2498 return 0;
2499}

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

2444{
2445 struct dahdi_pvt *p = pvt;
2446 int x = analogsub_to_dahdisub(sub);
2447
2448 return conf_add(p, &p->subs[x], x, 0);
2449}
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 2433 of file chan_dahdi.c.

2434{
2435 struct dahdi_pvt *p = pvt;
2436 int x = analogsub_to_dahdisub(sub);
2437
2438 return conf_del(p, &p->subs[x], x);
2439}

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

2353{
2354 struct dahdi_pvt *p = pvt;
2355 return dahdi_confmute(p, mute);
2356}

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

9311{
9312 int sent=0;
9313 int size;
9314 int res;
9315 int fd;
9316 fd = p->subs[idx].dfd;
9317 while (len) {
9318 size = len;
9319 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
9320 size = (linear ? READ_SIZE * 2 : READ_SIZE);
9321 res = write(fd, buf, size);
9322 if (res != size) {
9323 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
9324 return sent;
9325 }
9326 len -= size;
9327 buf += size;
9328 }
9329 return sent;
9330}

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

2034{
2035 struct dahdi_pvt *p = pvt;
2036
2038}

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

2980{
2981 struct dahdi_pvt *p = pvt;
2982
2983 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
2984 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
2985 return -1;
2986 }
2987
2988 if (sub != ANALOG_SUB_REAL) {
2989 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
2990 dop->dialstr, p->channel, sub);
2991 return -1;
2992 }
2993
2994 return dahdi_dial_str(p, DAHDI_DIAL_OP_REPLACE, dop->dialstr);
2995}
@ 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 1656 of file chan_dahdi.c.

1657{
1658 unsigned char buf[256];
1659 int distMatches;
1660 int curRingData[RING_PATTERNS];
1661 int receivedRingT;
1662 int counter1;
1663 int counter;
1664 int i;
1665 int res;
1666 int checkaftercid = 0;
1667 const char *matched_context;
1668 struct dahdi_pvt *p = pvt;
1669 struct analog_pvt *analog_p = p->sig_pvt;
1670
1671 if (ringdata == NULL) {
1672 ringdata = curRingData;
1673 } else {
1674 checkaftercid = 1;
1675 }
1676
1677 /* We must have a ring by now so lets try to listen for distinctive ringing */
1678 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
1679 /* Clear the current ring data array so we don't have old data in it. */
1680 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
1681 ringdata[receivedRingT] = 0;
1682 receivedRingT = 0;
1683
1684 if (checkaftercid && distinctiveringaftercid) {
1685 ast_verb(3, "Detecting post-CID distinctive ring\n");
1686 }
1687
1688 for (;;) {
1689 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
1690 res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i);
1691 if (res) {
1692 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
1693 ast_hangup(chan);
1694 return 1;
1695 }
1696 if (i & DAHDI_IOMUX_SIGEVENT) {
1697 res = dahdi_get_event(p->subs[idx].dfd);
1698 ast_debug(3, "Got event %d (%s)...\n", res, event2str(res));
1699 if (res == DAHDI_EVENT_NOALARM) {
1700 p->inalarm = 0;
1701 analog_p->inalarm = 0;
1702 } else if (res == DAHDI_EVENT_RINGOFFHOOK) {
1703 /* Let us detect distinctive ring */
1704 ringdata[receivedRingT] = analog_p->ringt;
1705
1706 if (analog_p->ringt < analog_p->ringt_base / 2) {
1707 break;
1708 }
1709 /* Increment the ringT counter so we can match it against
1710 values in chan_dahdi.conf for distinctive ring */
1711 if (++receivedRingT == RING_PATTERNS) {
1712 break;
1713 }
1714 }
1715 } else if (i & DAHDI_IOMUX_READ) {
1716 res = read(p->subs[idx].dfd, buf, sizeof(buf));
1717 if (res < 0) {
1718 if (errno != ELAST) {
1719 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1720 ast_hangup(chan);
1721 return 1;
1722 }
1723 break;
1724 }
1725 if (analog_p->ringt > 0) {
1726 if (!(--analog_p->ringt)) {
1727 break;
1728 }
1729 }
1730 }
1731 }
1732 }
1733
1734 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
1735 ast_verb(3, "Detected ring pattern: %d,%d,%d\n", ringdata[0], ringdata[1], ringdata[2]);
1736 matched_context = p->defcontext;
1737 for (counter = 0; counter < 3; counter++) {
1738 int range = p->drings.ringnum[counter].range;
1739
1740 distMatches = 0;
1741 ast_verb(3, "Checking %d,%d,%d with +/- %d range\n",
1742 p->drings.ringnum[counter].ring[0],
1743 p->drings.ringnum[counter].ring[1],
1744 p->drings.ringnum[counter].ring[2],
1745 range);
1746 for (counter1 = 0; counter1 < 3; counter1++) {
1747 int ring = p->drings.ringnum[counter].ring[counter1];
1748
1749 if (ring == -1) {
1750 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
1751 ringdata[counter1]);
1752 distMatches++;
1753 } else if (ring - range <= ringdata[counter1] && ringdata[counter1] <= ring + range) {
1754 ast_verb(3, "Ring pattern %d is in range: %d to %d\n",
1755 ringdata[counter1], ring - range, ring + range);
1756 distMatches++;
1757 } else {
1758 /* The current dring pattern cannot match. */
1759 break;
1760 }
1761 }
1762
1763 if (distMatches == 3) {
1764 /* The ring matches, set the context to whatever is for distinctive ring.. */
1765 matched_context = S_OR(p->drings.ringContext[counter].contextData, p->defcontext);
1766 ast_verb(3, "Matched Distinctive Ring context %s\n", matched_context);
1767 break;
1768 }
1769 }
1770
1771 /* Set selected distinctive ring context if not already set. */
1772 if (strcmp(p->context, matched_context) != 0) {
1773 ast_copy_string(p->context, matched_context, sizeof(p->context));
1774 ast_channel_context_set(chan, matched_context);
1775 }
1776
1777 return 0;
1778}
#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 1881 of file chan_dahdi.c.

1882{
1883 struct dahdi_pvt *p = pvt;
1884 if (p->dsp)
1886
1887 return 0;
1888}

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

1891{
1892 struct dahdi_pvt *p = pvt;
1893
1894 if (p->channel == CHAN_PSEUDO)
1895 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
1896
1897 if (mode == ANALOG_DIGITMODE_DTMF) {
1898 /* If we do hardware dtmf, no need for a DSP */
1899 if (p->hardwaredtmf) {
1900 if (p->dsp) {
1901 ast_dsp_free(p->dsp);
1902 p->dsp = NULL;
1903 }
1904 return 0;
1905 }
1906
1907 if (!p->dsp) {
1908 p->dsp = ast_dsp_new();
1909 if (!p->dsp) {
1910 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1911 return -1;
1912 }
1913 }
1914
1916 } else if (mode == ANALOG_DIGITMODE_MF) {
1917 if (!p->dsp) {
1918 p->dsp = ast_dsp_new();
1919 if (!p->dsp) {
1920 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1921 return -1;
1922 }
1923 }
1925 }
1926 return 0;
1927}
@ 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 2904 of file chan_dahdi.c.

2905{
2906 struct dahdi_pvt *p = pvt;
2907 int func = DAHDI_FLASH;
2908 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
2909}

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

2158{
2159 int res;
2160 struct dahdi_pvt *p = pvt;
2161
2162 res = get_alarms(p);
2163 handle_alarms(p, res);
2164}

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

1560{
1561 struct dahdi_pvt *p = pvt;
1562 struct analog_pvt *analog_p = p->sig_pvt;
1563 struct pollfd poller;
1564 char *name, *num;
1565 int index = SUB_REAL;
1566 int res;
1567 unsigned char buf[256];
1568 int flags;
1569 int redirecting;
1570
1571 poller.fd = p->subs[SUB_REAL].dfd;
1572 poller.events = POLLPRI | POLLIN;
1573 poller.revents = 0;
1574
1575 res = poll(&poller, 1, timeout);
1576
1577 if (poller.revents & POLLPRI) {
1579 return 1;
1580 }
1581
1582 if (poller.revents & POLLIN) {
1583 /*** NOTES ***/
1584 /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
1585 * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
1586 * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
1587 * a failure and die, and returning 2 means no event was received. */
1588 res = read(p->subs[index].dfd, buf, sizeof(buf));
1589 if (res < 0) {
1590 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1591 return -1;
1592 }
1593
1594 if (analog_p->ringt > 0) {
1595 if (!(--analog_p->ringt)) {
1596 /* only return if we timeout from a ring event */
1597 return -1;
1598 }
1599 }
1600
1601 if (p->cid_signalling == CID_SIG_V23_JP) {
1602 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
1603 } else {
1604 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
1605 }
1606 if (res < 0) {
1607 /*
1608 * The previous diagnostic message output likely
1609 * explains why it failed.
1610 */
1611 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
1612 return -1;
1613 }
1614
1615 if (res == 1) {
1616 struct ast_channel *chan = analog_p->ss_astchan;
1618 if (name)
1620 if (num)
1621 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
1622
1624 /* If we got a presentation, we must set it on the channel */
1625 struct ast_party_caller caller;
1626
1628 caller.id.name.presentation = caller.id.number.presentation = (flags & CID_PRIVATE_NUMBER) ?
1631 ast_party_caller_free(&caller);
1632 }
1633 if (redirecting) {
1634 /* There is a redirecting reason available in the Caller*ID received.
1635 * No idea what the redirecting number is, since the Caller*ID protocol
1636 * has no parameter for that, but at least we know WHY it was redirected. */
1637 ast_channel_redirecting(chan)->reason.code = redirecting;
1638 }
1639
1640 if (flags & CID_QUALIFIER) {
1641 /* This is the inverse of how the qualifier is set in sig_analog */
1642 pbx_builtin_setvar_helper(chan, "CALL_QUALIFIER", "1");
1643 }
1644
1645 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));
1646 return 0;
1647 }
1648 }
1649
1650 *ev = ANALOG_EVENT_NONE;
1651 return 2;
1652}
#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:1975
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:1967
void ast_party_caller_free(struct ast_party_caller *doomed)
Destroy the caller party contents.
Definition: channel.c:1983
#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:382
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 2840 of file chan_dahdi.c.

2841{
2842 struct dahdi_pvt *p = pvt;
2843 int res;
2844
2845 if (p->fake_event) {
2846 res = p->fake_event;
2847 p->fake_event = 0;
2848 } else
2849 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
2850
2851 return dahdievent_to_analogevent(res);
2852}

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

2372{
2373 struct dahdi_pvt *p = pvt;
2374
2375 return p->dialstring;
2376}

References dahdi_pvt::dialstring.

◆ my_get_sigpvt_bridged_channel()

static void * my_get_sigpvt_bridged_channel ( struct ast_channel chan)
static

Definition at line 2166 of file chan_dahdi.c.

2167{
2169
2170 if (bridged && ast_channel_tech(bridged) == &dahdi_tech) {
2171 struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
2172
2173 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
2174 return p->sig_pvt;
2175 }
2176 }
2177 return NULL;
2178}

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

2181{
2182 struct dahdi_pvt *p = pvt;
2183 int dahdi_sub = analogsub_to_dahdisub(sub);
2184 return p->subs[dahdi_sub].dfd;
2185}

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

9862{
9863 char c;
9864
9865 *str = 0; /* start with empty output buffer */
9866 for (;;)
9867 {
9868 /* Wait for the first digit (up to specified ms). */
9869 c = ast_waitfordigit(chan, ms);
9870 /* if timeout, hangup or error, return as such */
9871 if (c < 1)
9872 return c;
9873 *str++ = c;
9874 *str = 0;
9875 if (strchr(term, c))
9876 return 1;
9877 }
9878}
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 1947 of file chan_dahdi.c.

1948{
1949 struct ast_frame *f = *dest;
1950 struct dahdi_pvt *p = pvt;
1951 int idx = analogsub_to_dahdisub(analog_index);
1952
1953 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
1954 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
1955 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
1956
1957 if (f->subclass.integer == 'f') {
1958 if (f->frametype == AST_FRAME_DTMF_END) {
1959 /* Fax tone -- Handle and return NULL */
1960 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
1961 /* If faxbuffers are configured, use them for the fax transmission */
1962 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
1963 struct dahdi_bufferinfo bi = {
1964 .txbufpolicy = p->faxbuf_policy,
1965 .bufsize = p->bufsize,
1966 .numbufs = p->faxbuf_no
1967 };
1968 int res;
1969
1970 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
1971 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
1972 } else {
1973 p->bufferoverrideinuse = 1;
1974 }
1975 }
1976 p->faxhandled = 1;
1977 if (p->dsp) {
1978 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
1980 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
1981 }
1982 if (strcmp(ast_channel_exten(ast), "fax")) {
1983 const char *target_context = ast_channel_context(ast);
1984
1985 /*
1986 * We need to unlock 'ast' here because ast_exists_extension has the
1987 * potential to start autoservice on the channel. Such action is prone
1988 * to deadlock if the channel is locked.
1989 *
1990 * ast_async_goto() has its own restriction on not holding the
1991 * channel lock.
1992 */
1994 ast_channel_unlock(ast);
1995 if (ast_exists_extension(ast, target_context, "fax", 1,
1996 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
1997 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
1998 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
1999 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
2000 if (ast_async_goto(ast, target_context, "fax", 1))
2001 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
2002 } else {
2003 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
2004 }
2005 ast_channel_lock(ast);
2006 ast_mutex_lock(&p->lock);
2007 } else {
2008 ast_debug(1, "Already in a fax extension, not redirecting\n");
2009 }
2010 } else {
2011 ast_debug(1, "Fax already handled\n");
2012 }
2013 dahdi_confmute(p, 0);
2014 }
2015 p->subs[idx].f.frametype = AST_FRAME_NULL;
2016 p->subs[idx].f.subclass.integer = 0;
2017 *dest = &p->subs[idx].f;
2018 }
2019}

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

3619{
3620 struct dahdi_pvt *p = pvt;
3621
3622 if (neon_mwievent > -1 && !p->mwimonitor_neon)
3623 return;
3624
3625 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
3626 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
3627 notify_message(p->mailbox, 1);
3628 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
3629 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
3630 notify_message(p->mailbox, 0);
3631 }
3632 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
3633 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
3634 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
3635 ast_hangup(chan);
3636 return;
3637 }
3638}

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

2957{
2958 struct dahdi_pvt *p = pvt;
2959
2960 if (!p->hanguponpolarityswitch) {
2961 return;
2962 }
2963
2964 if (p->answeronpolarityswitch) {
2965 my_set_polarity(pvt, 0);
2966 } else {
2967 my_set_polarity(pvt, 1);
2968 }
2969}

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

2720{
2721 struct dahdi_pvt *p = pvt;
2722
2723 return has_voicemail(p);
2724}

References has_voicemail().

◆ my_have_progressdetect()

static int my_have_progressdetect ( void *  pvt)
static

Definition at line 3640 of file chan_dahdi.c.

3641{
3642 struct dahdi_pvt *p = pvt;
3643
3645 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3646 return 1;
3647 } else {
3648 /* Don't have progress detection. */
3649 return 0;
3650 }
3651}

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

3009{
3010 struct dahdi_pvt *p = pvt;
3011 int index;
3012 int x;
3013
3014 index = analogsub_to_dahdisub(sub);
3015
3016 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
3017 ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
3018 return -1;
3019 }
3020
3021 return x;
3022}

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

2855{
2856 struct dahdi_pvt *p = pvt;
2857 int res;
2858 struct dahdi_params par;
2859
2860 memset(&par, 0, sizeof(par));
2861
2862 if (p->subs[SUB_REAL].dfd > -1)
2863 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2864 else {
2865 /* Assume not off hook on CVRS */
2866 res = 0;
2867 par.rxisoffhook = 0;
2868 }
2869 if (res) {
2870 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
2871 }
2872
2873 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
2874 /* When "onhook" that means no battery on the line, and thus
2875 it is out of service..., if it's on a TDM card... If it's a channel
2876 bank, there is no telling... */
2877 return (par.rxbits > -1) || par.rxisoffhook;
2878 }
2879
2880 return par.rxisoffhook;
2881}

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

2022{
2023 struct dahdi_pvt *p = pvt;
2024 ast_mutex_lock(&p->lock);
2025}

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

2554{
2555 ast_callid callid = 0;
2556 int callid_created = ast_callid_threadstorage_auto(&callid);
2557 struct dahdi_pvt *p = pvt;
2558 int dsub = analogsub_to_dahdisub(sub);
2559
2560 return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, NULL, requestor, callid, callid_created);
2561}
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:9605

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

2914{
2915 struct dahdi_pvt *p = pvt;
2916 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2917}

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

3025{
3026 struct dahdi_pvt *p = pvt;
3027 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
3028}

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

2727{
2728 struct dahdi_pvt *p = pvt;
2729 int index;
2730
2731 index = analogsub_to_dahdisub(sub);
2732
2733 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
2734}
static int analog_tone_to_dahditone(enum analog_tone tone)
Definition: chan_dahdi.c:1363

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

2898{
2899 struct dahdi_pvt *p = pvt;
2900
2901 return dahdi_ring_phone(p);
2902}

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

1829{
1830 struct dahdi_pvt *p = pvt;
1831 struct analog_pvt *analog_p = p->sig_pvt;
1832
1833 ast_debug(2, "Starting cid spill\n");
1834
1835 if (p->cidspill) {
1836 ast_log(LOG_WARNING, "cidspill already exists??\n");
1837 ast_free(p->cidspill);
1838 }
1839
1841 int pres = ast_party_id_presentation(&caller->id);
1842 if (cwcid == 0) {
1843 /* Some CPE support additional parameters for on-hook Caller*ID,
1844 * such as redirecting reason and call qualifier, so send those
1845 * if available.
1846 * I don't know of any CPE that supports this for Call Waiting (unfortunately),
1847 * so don't send those for call waiting as that will just lengthen the CID spill
1848 * for no good reason.
1849 */
1851 caller->id.name.str,
1853 NULL,
1854 analog_p->redirecting_reason,
1855 pres,
1856 analog_p->call_qualifier,
1858 AST_LAW(p));
1859 } else {
1860 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
1862 p->callwaitcas = 0;
1863 p->cidcwexpire = 0;
1865 caller->id.name.str,
1867 NULL,
1868 -1,
1869 pres,
1870 0,
1871 AST_LAW(p));
1872 p->cidlen += READ_SIZE * 4;
1873 }
1874 p->cidpos = 0;
1875 p->cid_suppress_expire = 0;
1876 send_callerid(p);
1877 }
1878 return 0;
1879}
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:1789
int redirecting_reason
Definition: sig_analog.h:366
unsigned int call_qualifier
Definition: sig_analog.h:358
struct ast_party_caller caller
Definition: sig_analog.h:365

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

2207{
2208 struct dahdi_pvt *p = pvt;
2209
2210 p->inalarm = in_alarm;
2211}

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

2188{
2189 struct dahdi_pvt *p = pvt;
2190
2191 /* Choose proper cadence */
2192 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
2193 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
2194 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
2195 *cid_rings = cidrings[p->distinctivering - 1];
2196 } else {
2197 if (p->distinctivering > 0) {
2198 ast_log(LOG_WARNING, "Cadence %d is not defined, falling back to default ring cadence\n", p->distinctivering);
2199 }
2200 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
2201 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
2202 *cid_rings = p->sendcalleridafter;
2203 }
2204}

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

2337{
2338 struct dahdi_pvt *p = pvt;
2339
2340 p->callwaiting = callwaiting_enable;
2341}

References dahdi_pvt::callwaiting.

◆ my_set_confirmanswer()

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

Definition at line 2320 of file chan_dahdi.c.

2321{
2322 struct dahdi_pvt *p = pvt;
2323 p->confirmanswer = flag;
2324}

References dahdi_pvt::confirmanswer.

◆ my_set_dialing()

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

Definition at line 2213 of file chan_dahdi.c.

2214{
2215 struct dahdi_pvt *p = pvt;
2216
2217 p->dialing = is_dialing;
2218}

References dahdi_pvt::dialing.

◆ my_set_echocanceller()

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

Definition at line 2883 of file chan_dahdi.c.

2884{
2885 struct dahdi_pvt *p = pvt;
2886
2887 if (enable)
2888 dahdi_ec_enable(p);
2889 else
2891
2892 return 0;
2893}

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

2148{
2149 struct dahdi_pvt *p = pvt;
2150 int idx = analogsub_to_dahdisub(sub);
2151
2152 p->subs[idx].inthreeway = inthreeway;
2153}

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

2136{
2137 struct dahdi_pvt *p = pvt;
2138 int oldval;
2139 int idx = analogsub_to_dahdisub(sub);
2140
2141 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
2142 oldval = p->subs[idx].linear;
2143 p->subs[idx].linear = linear_mode ? 1 : 0;
2144 return oldval;
2145}

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

2920{
2921 struct dahdi_pvt *p = pvt;
2923}

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

2365{
2366 struct dahdi_pvt *p = pvt;
2367
2368 p->owner = new_owner;
2369}

References dahdi_pvt::owner.

◆ my_set_outgoing()

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

Definition at line 2220 of file chan_dahdi.c.

2221{
2222 struct dahdi_pvt *p = pvt;
2223
2224 p->outgoing = is_outgoing;
2225}

References dahdi_pvt::outgoing.

◆ my_set_polarity()

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

Definition at line 2925 of file chan_dahdi.c.

2926{
2927 struct dahdi_pvt *p = pvt;
2928
2929 if (p->channel == CHAN_PSEUDO) {
2930 return;
2931 }
2932 p->polarity = value;
2933 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
2934}

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

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

◆ my_set_pulsedial()

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

Definition at line 2358 of file chan_dahdi.c.

2359{
2360 struct dahdi_pvt *p = pvt;
2361 p->pulsedial = flag;
2362}

References dahdi_pvt::pulsedial.

◆ my_set_ringtimeout()

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

Definition at line 2263 of file chan_dahdi.c.

2264{
2265 struct dahdi_pvt *p = pvt;
2266 p->ringt = ringt;
2267}

References dahdi_pvt::ringt.

◆ my_set_waitingfordt()

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

Definition at line 2269 of file chan_dahdi.c.

2270{
2271 struct dahdi_pvt *p = pvt;
2272
2273 /* We reset p->waitfordialtonetemp here, to prevent leaking to future calls,
2274 * but we also need to check against this value until we get dialtone
2275 * or the timer expires, since waitingfordt is when the timer started,
2276 * not when it should expire.
2277 *
2278 * Critically, we only set p->waitingfordt here if waitfordialtone or waitfordialtonetemp
2279 * has already been set, as waitingfordt is what is checked at runtime to determine
2280 * if we should be waiting for dial tone. This ensures that if a second call
2281 * is initiated concurrently, the first one "consumes" waitfordialtonetemp and resets it,
2282 * preventing leaking to other calls while remaining available to check on the first one while dialing.
2283 */
2285 p->waitfordialtonetemp = 0;
2286
2288 return;
2289 }
2290
2291 /* Because the DSP is allocated when the channel is created,
2292 * if we requested waitfordialtone later (in a predial handler),
2293 * we need to create it now */
2294 if (!p->dsp) {
2295 p->dsp = ast_dsp_new();
2296 if (!p->dsp) {
2297 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
2298 return;
2299 }
2300 }
2303
2304 ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtoneduration);
2305 gettimeofday(&p->waitingfordt, NULL);
2307}
@ 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 2971 of file chan_dahdi.c.

2972{
2973 struct dahdi_pvt *p = pvt;
2974 int x = DAHDI_START;
2975
2976 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2977}

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

1527{
1528 struct dahdi_pvt *p = pvt;
1529 int index = SUB_REAL;
1531 if (!p->cs) {
1532 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
1533 return -1;
1534 }
1535 bump_gains(p);
1536 dahdi_setlinear(p->subs[index].dfd, 0);
1537
1538 return 0;
1539}

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

2937{
2938 struct dahdi_pvt *p = pvt;
2939
2941 my_set_polarity(pvt, 0);
2942 }
2943}

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

1781{
1782 struct dahdi_pvt *p = pvt;
1783 p->callwaitingrepeat = 0;
1784 p->cidcwexpire = 0;
1785 p->cid_suppress_expire = 0;
1786
1787 return 0;
1788}

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

1544{
1545 struct dahdi_pvt *p = pvt;
1546 int index = SUB_REAL;
1547
1548 if (p->cs) {
1549 callerid_free(p->cs);
1550 }
1551
1552 /* Restore linear mode after Caller*ID processing */
1553 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
1554 restore_gains(p);
1555
1556 return 0;
1557}

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

2510{
2511 struct dahdi_pvt *p = pvt;
2512 int da, db;
2513 int tchan;
2514 int tinthreeway;
2515
2518
2519 tchan = p->subs[da].chan;
2520 p->subs[da].chan = p->subs[db].chan;
2521 p->subs[db].chan = tchan;
2522
2523 tinthreeway = p->subs[da].inthreeway;
2524 p->subs[da].inthreeway = p->subs[db].inthreeway;
2525 p->subs[db].inthreeway = tinthreeway;
2526
2527 p->subs[da].owner = ast_a;
2528 p->subs[db].owner = ast_b;
2529
2530 if (ast_a)
2531 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
2532 if (ast_b)
2533 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
2534
2535 wakeup_sub(p, a);
2536 wakeup_sub(p, b);
2537
2538 return;
2539}
static sqlite3 * db
static void wakeup_sub(struct dahdi_pvt *p, int a)
Definition: chan_dahdi.c:3790
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 2999 of file chan_dahdi.c.

3000{
3001 struct dahdi_pvt *p = pvt;
3002
3003 dahdi_train_ec(p);
3004
3005 return 0;
3006}

References dahdi_train_ec().

◆ my_unallocate_sub()

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

Definition at line 2701 of file chan_dahdi.c.

2702{
2703 struct dahdi_pvt *p = pvt;
2704
2705 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
2706}

References analogsub_to_dahdisub(), and unalloc_sub().

◆ my_unlock_private()

static void my_unlock_private ( void *  pvt)
static

Definition at line 2027 of file chan_dahdi.c.

2028{
2029 struct dahdi_pvt *p = pvt;
2031}

References ast_mutex_unlock, and dahdi_pvt::lock.

◆ my_wait_event()

static int my_wait_event ( void *  pvt)
static

Definition at line 2833 of file chan_dahdi.c.

2834{
2835 struct dahdi_pvt *p = pvt;
2836
2837 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
2838}

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

1932{
1933 struct dahdi_pvt *p = pvt;
1934 int index = analogsub_to_dahdisub(sub);
1935 if (index != SUB_REAL) {
1936 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
1937 }
1938 return dahdi_wink(p, index);
1939}

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

3604{
3605 char s[sizeof(mwimonitornotify) + 164];
3606
3607 if (ast_strlen_zero(mailbox)) {
3608 return;
3609 }
3610
3611 ast_publish_mwi_state(mailbox, NULL, thereornot, thereornot);
3613 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
3614 ast_safe_system(s);
3615 }
3616}
static char mwimonitornotify[PATH_MAX]
Definition: chan_dahdi.c:851
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:827
#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 7262 of file chan_dahdi.c.

7263{
7264 int res;
7265 char policy_str[21] = "";
7266
7267 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
7268 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
7269 return 1;
7270 }
7271 if (*num_buffers < 0) {
7272 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
7273 return -1;
7274 }
7275 if (!strcasecmp(policy_str, "full")) {
7276 *policy = DAHDI_POLICY_WHEN_FULL;
7277 } else if (!strcasecmp(policy_str, "immediate")) {
7278 *policy = DAHDI_POLICY_IMMEDIATE;
7279#if defined(HAVE_DAHDI_HALF_FULL)
7280 } else if (!strcasecmp(policy_str, "half")) {
7281 *policy = DAHDI_POLICY_HALF_FULL;
7282#endif
7283 } else {
7284 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
7285 return -1;
7286 }
7287
7288 return 0;
7289}

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

18731{
18732 int count_pattern = 0;
18733 int norval = 0;
18734 char *temp = NULL;
18735
18736 for (; ;) {
18737 /* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
18738 if (!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
18739 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18740 break;
18741 }
18742
18743 busy_cadence->pattern[count_pattern] = norval;
18744
18745 count_pattern++;
18746 if (count_pattern == 4) {
18747 break;
18748 }
18749
18750 temp = strchr(v->value, ',');
18751 if (temp == NULL) {
18752 break;
18753 }
18754 v->value = temp + 1;
18755 }
18756 busy_cadence->length = count_pattern;
18757
18758 if (count_pattern % 2 != 0) {
18759 /* The pattern length must be divisible by two */
18760 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18761 }
18762
18763}

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
Todo:
The standalone POLARITY function can and should be deprecated/removed, since its functionality is now part of DAHDI_CHANNEL.

Definition at line 17045 of file chan_dahdi.c.

17046{
17047 struct dahdi_params dahdip;
17048 struct dahdi_pvt *pvt = ast_channel_tech_pvt(chan);
17049 if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
17050 ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", ast_channel_name(chan));
17051 return -1;
17052 }
17053 memset(&dahdip, 0, sizeof(dahdip));
17054 if (ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &dahdip)) {
17055 ast_log(LOG_WARNING, "Unable to get parameters of DAHDI channel %d: %s\n", pvt->subs[SUB_REAL].dfd, strerror(errno));
17056 return -1;
17057 }
17058 return dahdichan_read_property(ast_channel_tech_pvt(chan), &dahdip, "polarity", buffer, buflen);
17059}

References ast_channel_name(), ast_channel_tech(), ast_channel_tech_pvt(), ast_log, dahdichan_read_property(), dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, dahdi_pvt::subs, and type.

◆ polarity_write()

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

Definition at line 17061 of file chan_dahdi.c.

17062{
17063 struct dahdi_params dahdip;
17064 struct dahdi_pvt *pvt = ast_channel_tech_pvt(chan);
17065 if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
17066 ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", ast_channel_name(chan));
17067 return -1;
17068 }
17069 memset(&dahdip, 0, sizeof(dahdip));
17070 if (ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &dahdip)) {
17071 ast_log(LOG_WARNING, "Unable to get parameters of DAHDI channel %d: %s\n", pvt->subs[SUB_REAL].dfd, strerror(errno));
17072 return -1;
17073 }
17074 return dahdichan_write_property(ast_channel_tech_pvt(chan), &dahdip, "polarity", value);
17075}

References ast_channel_name(), ast_channel_tech(), ast_channel_tech_pvt(), ast_log, dahdichan_write_property(), dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, dahdi_pvt::subs, type, and value.

◆ print_subchannel()

static int print_subchannel ( struct dahdi_pvt p,
int  subchan,
char *  buffer,
size_t  len 
)
static

Definition at line 16883 of file chan_dahdi.c.

16884{
16885 if (!p->subs[subchan].owner) {
16886 return -1;
16887 }
16888 ast_channel_lock(p->subs[subchan].owner);
16889 snprintf(buffer, len, "%s", ast_channel_name(p->subs[subchan].owner));
16890 ast_channel_unlock(p->subs[subchan].owner);
16891 return 0;
16892}

References ast_channel_lock, ast_channel_name(), ast_channel_unlock, len(), dahdi_subchannel::owner, and dahdi_pvt::subs.

Referenced by dahdichan_read_property().

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

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

18594{
18595 char *parse = ast_strdupa(data);
18596 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
18597 unsigned int param_count;
18598 unsigned int x;
18599
18600 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
18601 return;
18602
18603 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
18604
18605 /* first parameter is tap length, process it here */
18606
18607 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
18608
18609 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
18610 confp->chan.echocancel.head.tap_length = x;
18611 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
18612 confp->chan.echocancel.head.tap_length = 128;
18613
18614 /* now process any remaining parameters */
18615
18616 for (x = 1; x < param_count; x++) {
18617 struct {
18618 char *name;
18619 char *value;
18620 } param;
18621
18622 if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
18623 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
18624 continue;
18625 }
18626
18627 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
18628 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
18629 continue;
18630 }
18631
18632 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
18633
18634 if (param.value) {
18635 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
18636 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
18637 continue;
18638 }
18639 }
18640 confp->chan.echocancel.head.param_count++;
18641 }
18642}
#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 7768 of file chan_dahdi.c.

7769{
7770 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7771 RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
7772 if (!dahdi_chan) {
7773 return;
7774 }
7775
7776 ast_str_set(&dahdi_chan, 0, "%d", channel);
7777 body = ast_json_pack("{s: s, s: s}",
7778 "DAHDIChannel", ast_str_buffer(dahdi_chan),
7779 "Alarm", alarm_txt);
7780 if (!body) {
7781 return;
7782 }
7783
7785}
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
Definition: manager.c:634
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 3815 of file chan_dahdi.c.

3816{
3817 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3818 RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
3819 if (!dahdi_chan) {
3820 return;
3821 }
3822
3823 ast_str_set(&dahdi_chan, 0, "%d", channel);
3824 ast_log(LOG_NOTICE, "Alarm cleared on channel DAHDI/%d\n", channel);
3825 body = ast_json_pack("{s: s}", "DAHDIChannel", ast_str_buffer(dahdi_chan));
3826 if (!body) {
3827 return;
3828 }
3829
3830 ast_manager_publish_event("AlarmClear", EVENT_FLAG_SYSTEM, body);
3831}

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

2072{
2073 RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
2074
2075 ast_assert(dahdi_channel != NULL);
2076
2077 blob = ast_json_pack("{s: I, s: i, s: s}",
2078 "group", (ast_json_int_t)group,
2079 "span", span,
2080 "channel", dahdi_channel);
2081 if (!blob) {
2082 return;
2083 }
2084
2085 ast_channel_lock(chan);
2086 ast_channel_publish_blob(chan, dahdichannel_type(), blob);
2087 ast_channel_unlock(chan);
2088}
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:776

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

9899{
9900 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
9901 RAII_VAR(struct ast_str *, dahdichan, ast_str_create(32), ast_free);
9902 if (!dahdichan) {
9903 return;
9904 }
9905
9906 ast_str_set(&dahdichan, 0, "%d", channel);
9907
9908 body = ast_json_pack("{s: s, s: s}",
9909 "DAHDIChannel", ast_str_buffer(dahdichan),
9910 "Status", status);
9911 if (!body) {
9912 return;
9913 }
9914
9916}
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 7754 of file chan_dahdi.c.

7755{
7756 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7757
7758 body = ast_json_pack("{s: i, s: s}",
7759 "Span", span,
7760 "Alarm", alarm_txt);
7761 if (!body) {
7762 return;
7763 }
7764
7765 ast_manager_publish_event("SpanAlarm", EVENT_FLAG_SYSTEM, body);
7766}

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

3834{
3835 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3836
3837 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", span);
3838 body = ast_json_pack("{s: i}", "Span", span);
3839 if (!body) {
3840 return;
3841 }
3842
3843 ast_manager_publish_event("SpanAlarmClear", EVENT_FLAG_SYSTEM, body);
3844}

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

1414{
1415#ifdef HAVE_PRI
1416 struct doomed_pri *entry;
1417
1418 AST_LIST_LOCK(&doomed_pris);
1419 while ((entry = AST_LIST_REMOVE_HEAD(&doomed_pris, list))) {
1420 /* The span destruction must be done with this lock not held */
1421 AST_LIST_UNLOCK(&doomed_pris);
1422 ast_debug(4, "Destroying span %d from doomed queue.\n",
1423 entry->pri->span);
1424 pri_destroy_span(entry->pri);
1425 ast_free(entry);
1426 AST_LIST_LOCK(&doomed_pris);
1427 }
1428 AST_LIST_UNLOCK(&doomed_pris);
1429#endif
1430}
#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 20732 of file chan_dahdi.c.

20733{
20734 int res = 0;
20735
20736 res = setup_dahdi(1);
20737 if (res) {
20738 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
20739 return -1;
20740 }
20741 return 0;
20742}

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

4880{
4881 p->confno = -1;
4882 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
4883 if (p->subs[SUB_REAL].dfd > -1) {
4884 struct dahdi_confinfo zi;
4885
4886 memset(&zi, 0, sizeof(zi));
4887 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
4888 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
4889 }
4890 return 0;
4891}

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

12258{
12259 /* If we're supposed to be stopped -- stay stopped */
12261 return 0;
12263 if (monitor_thread == pthread_self()) {
12265 ast_log(LOG_WARNING, "Cannot kill myself\n");
12266 return -1;
12267 }
12269 /* Wake up the thread */
12270 pthread_kill(monitor_thread, SIGURG);
12271 } else {
12272 /* Start a new monitor */
12275 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12276 return -1;
12277 }
12278 }
12280 return 0;
12281}
static void * do_monitor(void *data)
Definition: chan_dahdi.c:11943

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

5313{
5314 int res;
5315 if (p->saveconf.confmode) {
5316 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
5317 p->saveconf.confmode = 0;
5318 if (res) {
5319 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
5320 return -1;
5321 }
5322 ast_debug(1, "Restored conferencing\n");
5323 }
5324 return 0;
5325}
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 5219 of file chan_dahdi.c.

5220{
5221 int res;
5222
5223 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5224 if (res) {
5225 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
5226 return -1;
5227 }
5228
5229 return 0;
5230}

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

6279{
6280 if (p->bufferoverrideinuse) {
6281 /* faxbuffers are in use, revert them */
6282 struct dahdi_bufferinfo bi = {
6283 .txbufpolicy = p->buf_policy,
6284 .rxbufpolicy = p->buf_policy,
6285 .bufsize = p->bufsize,
6286 .numbufs = p->buf_no
6287 };
6288 int bpres;
6289
6290 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
6291 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
6292 }
6293 p->bufferoverrideinuse = 0;
6294 return bpres;
6295 }
6296
6297 return -1;
6298}

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

5287{
5288 struct dahdi_confinfo c;
5289 int res;
5290 if (p->saveconf.confmode) {
5291 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
5292 return -1;
5293 }
5294 p->saveconf.chan = 0;
5295 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
5296 if (res) {
5297 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
5298 p->saveconf.confmode = 0;
5299 return -1;
5300 }
5301 memset(&c, 0, sizeof(c));
5302 c.confmode = DAHDI_CONF_NORMAL;
5303 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
5304 if (res) {
5305 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
5306 return -1;
5307 }
5308 ast_debug(1, "Disabled conferencing\n");
5309 return 0;
5310}

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

5374{
5375 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
5376 int res;
5377 /* Take out of linear mode if necessary */
5378 if (p->subs[SUB_REAL].linear) {
5379 p->subs[SUB_REAL].linear = 0;
5381 }
5382 while (p->cidpos < p->cidlen) {
5383 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
5384 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
5385 if (res < 0) {
5386 if (errno == EAGAIN)
5387 return 0;
5388 else {
5389 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5390 return -1;
5391 }
5392 }
5393 if (!res)
5394 return 0;
5395 p->cidpos += res;
5396 }
5398 ast_free(p->cidspill);
5399 p->cidspill = NULL;
5400 if (p->callwaitcas) {
5401 /* Wait for CID/CW to expire */
5404 } else
5406 return 0;
5407}
#define CALLWAITING_SUPPRESS_SAMPLES
Definition: chan_dahdi.c:931
#define CIDCW_EXPIRE_SAMPLES
Definition: chan_dahdi.c:932

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

5328{
5329 p->callwaitcas = 0;
5330 p->cidcwexpire = 0;
5331 p->cid_suppress_expire = 0;
5333 return -1;
5335 /* Make sure we account for the end */
5336 p->cidlen += READ_SIZE * 4;
5337 p->cidpos = 0;
5338 send_callerid(p);
5339 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
5340 return 0;
5341}
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 5200 of file chan_dahdi.c.

5201{
5202 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
5203}

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

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

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

5167{
5168 struct dahdi_gains g;
5169 int res;
5170
5171 memset(&g, 0, sizeof(g));
5172 res = ioctl(fd, DAHDI_GETGAINS, &g);
5173 if (res) {
5174 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
5175 return res;
5176 }
5177
5178 fill_txgain(&g, gain, drc, law);
5179
5180 return ioctl(fd, DAHDI_SETGAINS, &g);
5181}
static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
Definition: chan_dahdi.c:5068

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

5039{
5040 struct dahdi_hwgain hwgain;
5041
5042 hwgain.newgain = gain * 10.0;
5043 hwgain.tx = tx_direction;
5044 return ioctl(fd, DAHDI_SET_HWGAIN, &hwgain) < 0;
5045}

Referenced by dahdi_set_hwgain(), and mkintf().

◆ setup_dahdi()

static int setup_dahdi ( int  reload)
static

Definition at line 20472 of file chan_dahdi.c.

20473{
20474 int res;
20475 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
20476 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
20478
20479 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
20480 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
20481 } else {
20482 res = -1;
20483 }
20486 ast_cc_config_params_destroy(conf.chan.cc_params);
20487
20488 return res;
20489}

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

20242{
20243 struct ast_config *cfg;
20244 struct ast_config;
20245 struct ast_variable *v;
20246 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
20247 const char *chans;
20248 const char *cat;
20249 int res;
20250
20251#ifdef HAVE_PRI
20252 char *c;
20253 int spanno;
20254 int i;
20255 int logicalspan;
20256 int trunkgroup;
20257 int dchannels[SIG_PRI_NUM_DCHANS];
20258#endif
20259 int have_cfg_now;
20260 static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
20261
20262 cfg = ast_config_load(config, config_flags);
20263 have_cfg_now = !!cfg;
20264 if (!cfg) {
20265 /* Error if we have no config file */
20266 if (had_cfg_before) {
20267 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
20269 }
20270 cfg = ast_config_new();/* Dummy config */
20271 if (!cfg) {
20272 return 0;
20273 }
20274 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
20276 cfg = ast_config_load(config, config_flags);
20277 have_cfg_now = !!cfg;
20278 if (!cfg) {
20279 if (had_cfg_before) {
20280 /* We should have been able to load the config. */
20281 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
20282 return 0;
20283 }
20284 cfg = ast_config_new();/* Dummy config */
20285 if (!cfg) {
20286 return 0;
20287 }
20288 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
20289 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
20290 return 0;
20291 }
20292 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
20293 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
20294 return 0;
20295 } else {
20297 }
20298 had_cfg_before = have_cfg_now;
20299
20300 /* It's a little silly to lock it, but we might as well just to be sure */
20302#ifdef HAVE_PRI
20303 if (reload != 1) {
20304 /* Process trunkgroups first */
20305 v = ast_variable_browse(cfg, "trunkgroups");
20306 while (v) {
20307 if (!strcasecmp(v->name, "trunkgroup")) {
20308 trunkgroup = atoi(v->value);
20309 if (trunkgroup > 0) {
20310 if ((c = strchr(v->value, ','))) {
20311 i = 0;
20312 memset(dchannels, 0, sizeof(dchannels));
20313 while (c && (i < SIG_PRI_NUM_DCHANS)) {
20314 dchannels[i] = atoi(c + 1);
20315 if (dchannels[i] < 0) {
20316 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);
20317 } else
20318 i++;
20319 c = strchr(c + 1, ',');
20320 }
20321 if (i) {
20322 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
20323 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);
20324 } else
20325 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");
20326 } else
20327 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
20328 } else
20329 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
20330 } else
20331 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
20332 } else if (!strcasecmp(v->name, "spanmap")) {
20333 spanno = atoi(v->value);
20334 if (spanno > 0) {
20335 if ((c = strchr(v->value, ','))) {
20336 trunkgroup = atoi(c + 1);
20337 if (trunkgroup > 0) {
20338 if ((c = strchr(c + 1, ',')))
20339 logicalspan = atoi(c + 1);
20340 else
20341 logicalspan = 0;
20342 if (logicalspan >= 0) {
20343 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
20344 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
20345 } else
20346 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
20347 } else
20348 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);
20349 } else
20350 ast_log(LOG_WARNING, "Trunk group must be a positive number at line %d of chan_dahdi.conf\n", v->lineno);
20351 } else
20352 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
20353 } else
20354 ast_log(LOG_WARNING, "Span number must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
20355 } else {
20356 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
20357 }
20358 v = v->next;
20359 }
20360 }
20361#endif
20362
20363 /* Copy the default jb config over global_jbconf */
20364 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
20365
20366 mwimonitornotify[0] = '\0';
20367
20368 v = ast_variable_browse(cfg, "channels");
20369 if ((res = process_dahdi(base_conf,
20370 "" /* Must be empty for the channels category. Silly voicemail mailbox. */,
20371 v, reload, 0))) {
20373 ast_config_destroy(cfg);
20374 return res;
20375 }
20376
20377 /* Now get configuration from all normal sections in chan_dahdi.conf: */
20378 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
20379 /* [channels] and [trunkgroups] are used. Let's also reserve
20380 * [globals] and [general] for future use
20381 */
20382 if (!strcasecmp(cat, "general") ||
20383 !strcasecmp(cat, "trunkgroups") ||
20384 !strcasecmp(cat, "globals") ||
20385 !strcasecmp(cat, "channels")) {
20386 continue;
20387 }
20388
20389 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
20390 if (ast_strlen_zero(chans)) {
20391 /* Section is useless without a dahdichan value present. */
20392 continue;
20393 }
20394
20395 /* Copy base_conf to conf. */
20396 deep_copy_dahdi_chan_conf(conf, base_conf);
20397
20398 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
20400 ast_config_destroy(cfg);
20401 return res;
20402 }
20403 }
20404
20405 ast_config_destroy(cfg);
20407
20408#ifdef HAVE_PRI
20409 if (reload != 1) {
20410 int x;
20411 for (x = 0; x < NUM_SPANS; x++) {
20412 if (pris[x].pri.pvts[0] &&
20413 pris[x].pri.master == AST_PTHREADT_NULL) {
20414 prepare_pri(pris + x);
20415 if (sig_pri_start_pri(&pris[x].pri)) {
20416 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
20417 return -1;
20418 } else
20419 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
20420 }
20421 }
20422 }
20423#endif
20424#if defined(HAVE_SS7)
20425 if (reload != 1) {
20426 int x;
20427 for (x = 0; x < NUM_SPANS; x++) {
20428 if (linksets[x].ss7.ss7) {
20429 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
20430 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
20431 return -1;
20432 } else
20433 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
20434 }
20435 }
20436 }
20437#endif /* defined(HAVE_SS7) */
20438#ifdef HAVE_OPENR2
20439 if (reload != 1) {
20440 struct r2link_entry *cur;
20441 int x = 0;
20442 AST_LIST_LOCK(&r2links);
20443 AST_LIST_TRAVERSE(&r2links, cur, list) {
20444 struct dahdi_mfcr2 *r2 = &cur->mfcr2;
20445 if (r2->r2master == AST_PTHREADT_NULL) {
20446 if (ast_pthread_create(&r2->r2master, NULL, mfcr2_monitor, r2)) {
20447 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
20448 return -1;
20449 } else {
20450 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
20451 }
20452 x++;
20453 }
20454 }
20455 AST_LIST_UNLOCK(&r2links);
20456 }
20457#endif
20458 /* And start the monitor for the first time */
20460 return 0;
20461}
static struct chans chans
static struct ast_jb_conf default_jbconf
Definition: chan_dahdi.c:748
static const char config[]
Definition: chan_dahdi.c:799
static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
Definition: chan_dahdi.c:18765
static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
Definition: chan_dahdi.c:20219
#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:3324
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3272
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1287
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:870
@ CONFIG_FLAG_FILEUNCHANGED
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1213
#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:217
Definition: astman.c:88
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:621

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

12564{
12565 return sigtype;
12566}
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 4368 of file chan_dahdi.c.

4369{
4370 int tchan;
4371 int tinthreeway;
4372 struct ast_channel *towner;
4373
4374 ast_debug(1, "Swapping %d and %d\n", a, b);
4375
4376 tchan = p->subs[a].chan;
4377 towner = p->subs[a].owner;
4378 tinthreeway = p->subs[a].inthreeway;
4379
4380 p->subs[a].chan = p->subs[b].chan;
4381 p->subs[a].owner = p->subs[b].owner;
4382 p->subs[a].inthreeway = p->subs[b].inthreeway;
4383
4384 p->subs[b].chan = tchan;
4385 p->subs[b].owner = towner;
4386 p->subs[b].inthreeway = tinthreeway;
4387
4388 if (p->subs[a].owner)
4389 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
4390 if (p->subs[b].owner)
4391 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
4392 wakeup_sub(p, a);
4393 wakeup_sub(p, b);
4394}

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

4515{
4516 if (!x) {
4517 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
4518 return -1;
4519 }
4520 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
4521 dahdi_close_sub(p, x);
4522 p->subs[x].linear = 0;
4523 p->subs[x].chan = 0;
4524 p->subs[x].owner = NULL;
4525 p->subs[x].inthreeway = 0;
4527 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
4528 return 0;
4529}

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

18517{
18518#if defined(HAVE_PRI) || defined(HAVE_SS7)
18519 int y;
18520#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18521#ifdef HAVE_PRI
18522 for (y = 0; y < NUM_SPANS; y++)
18523 ast_mutex_destroy(&pris[y].pri.lock);
18524#endif
18525#if defined(HAVE_SS7)
18526 for (y = 0; y < NUM_SPANS; y++)
18527 ast_mutex_destroy(&linksets[y].ss7.lock);
18528#endif /* defined(HAVE_SS7) */
18529 return __unload_module();
18530}

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

3791{
3793 if (p->subs[a].owner) {
3796 }
3797}
static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
Definition: chan_dahdi.c:3774

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

◆ alarm

int alarm

Definition at line 4670 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 3666 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 839 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 20756 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 831 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 799 of file chan_dahdi.c.

Referenced by setup_dahdi_int().

◆ dahdi_cli

struct ast_cli_entry dahdi_cli[]
static

Definition at line 16814 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

◆ dahdi_tech

struct ast_channel_tech dahdi_tech
static

◆ dahdichan_function

struct ast_custom_function dahdichan_function
static
Initial value:
= {
.name = "DAHDI_CHANNEL",
.write = dahdichan_write,
.read = dahdichan_read,
}
static int dahdichan_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: chan_dahdi.c:17032
static int dahdichan_read(struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)
Definition: chan_dahdi.c:17027

Definition at line 17037 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

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

Referenced by setup_dahdi_int().

◆ defaultcic

char defaultcic[64] = ""
static

Definition at line 847 of file chan_dahdi.c.

Referenced by process_dahdi().

◆ defaultozz

char defaultozz[64] = ""
static

Definition at line 848 of file chan_dahdi.c.

Referenced by process_dahdi().

◆ distinctiveringaftercid

int distinctiveringaftercid = 0
static

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

Referenced by do_monitor(), and process_dahdi().

◆ events

const char* const events[]
static

Definition at line 4647 of file chan_dahdi.c.

Referenced by event2str().

◆ global_jbconf

struct ast_jb_conf global_jbconf
static

Definition at line 756 of file chan_dahdi.c.

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

◆ has_pseudo

int has_pseudo
static

Definition at line 818 of file chan_dahdi.c.

Referenced by build_channels(), and process_dahdi().

◆ ifcount

int ifcount = 0
static

Definition at line 879 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 1053 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 735 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 891 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 887 of file chan_dahdi.c.

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

◆ mwilevel

int mwilevel = 512
static

Definition at line 863 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 851 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 853 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 815 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 861 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:17045
static int polarity_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: chan_dahdi.c:17061

Definition at line 17077 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

◆ progzone

char progzone[10] = ""
static

Definition at line 856 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

◆ report_alarms

int report_alarms = REPORT_CHANNEL_ALARMS
static

Definition at line 868 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 894 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 941 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 3740 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 1046 of file chan_dahdi.c.

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

◆ tdesc

const char tdesc[] = "DAHDI Telephony"
static

Definition at line 778 of file chan_dahdi.c.

◆ usedistinctiveringdetection

int usedistinctiveringdetection = 0
static

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

Referenced by process_dahdi().