Asterisk - The Open Source Telephony Project GIT-master-545c459
Loading...
Searching...
No Matches
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_IS_FXO_SIG(sig)   (sig == SIG_FXOKS || sig == SIG_FXOLS || sig == SIG_FXOGS)
 
#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.
 
#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 IS_FXO_SIG(p)   (((p)->sig == SIG_FXOKS) || ((p)->sig == SIG_FXOLS) || ((p)->sig == SIG_FXOGS))
 Whether a channel is FXO signaled.
 
#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.
 
#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().
 
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
 
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.
 
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.
 
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.
 
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.
 
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.
 
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 = ASTERISK_GPL_KEY , .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.
 
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 = AST_MUTEX_INIT_VALUE
 Protect the interface list (of dahdi_pvt's)
 
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.
 
static ast_mutex_t monlock = AST_MUTEX_INIT_VALUE
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
 
static int mwilevel = 512
 
static char mwimonitornotify [PATH_MAX] = ""
 
static int mwisend_rpas = 0
 
static int num_cadence = 4
 
static int num_restart_pending = 0
 
static int numbufs = 4
 
static struct ast_custom_function polarity_function
 
static char progzone [10] = ""
 
static int report_alarms = REPORT_CHANNEL_ALARMS
 
static ast_mutex_t restart_lock = AST_MUTEX_INIT_VALUE
 
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base.
 
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 = AST_MUTEX_INIT_VALUE
 
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 816 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX_INCOMING

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 815 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX_OUTGOING

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 814 of file chan_dahdi.c.

◆ CALLPROGRESS_PROGRESS

#define CALLPROGRESS_PROGRESS   1

Definition at line 813 of file chan_dahdi.c.

◆ CALLWAITING_REPEAT_SAMPLES

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

10,000 ms

Definition at line 934 of file chan_dahdi.c.

◆ CALLWAITING_SILENT_SAMPLES

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

300 ms

Definition at line 933 of file chan_dahdi.c.

◆ CALLWAITING_SUPPRESS_SAMPLES

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

100 ms

Definition at line 935 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 848 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 849 of file chan_dahdi.c.

◆ CHAN_IS_FXO_SIG

#define CHAN_IS_FXO_SIG (   sig)    (sig == SIG_FXOKS || sig == SIG_FXOLS || sig == SIG_FXOGS)

Definition at line 780 of file chan_dahdi.c.

◆ CHAN_PSEUDO

#define CHAN_PSEUDO   -2

Definition at line 811 of file chan_dahdi.c.

◆ CIDCW_EXPIRE_SAMPLES

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

500 ms

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

◆ DEFAULT_RINGT

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

8,000 ms

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

3659 { \
3660 struct dahdi_pvt *p = pvt; \
3661 return p->field; \
3662 }

◆ GET_CHANNEL

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

Definition at line 1314 of file chan_dahdi.c.

◆ HANGUP

#define HANGUP   1

Definition at line 16840 of file chan_dahdi.c.

◆ HEADER_LEN

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

◆ HEADER_MS

#define HEADER_MS   50

◆ IS_FXO_SIG

#define IS_FXO_SIG (   p)    (((p)->sig == SIG_FXOKS) || ((p)->sig == SIG_FXOLS) || ((p)->sig == SIG_FXOGS))

Whether a channel is FXO signaled.

Definition at line 779 of file chan_dahdi.c.

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

◆ MASK_AVAIL

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 930 of file chan_dahdi.c.

◆ MASK_INUSE

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

◆ MIN_MS_SINCE_FLASH

#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

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

◆ NUM_SPANS

#define NUM_SPANS   32

Definition at line 808 of file chan_dahdi.c.

◆ POLARITY_IDLE

#define POLARITY_IDLE   0

Definition at line 1047 of file chan_dahdi.c.

◆ POLARITY_REV

#define POLARITY_REV   1

Definition at line 1048 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 18736 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 18738 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 928 of file chan_dahdi.c.

◆ REPORT_CHANNEL_ALARMS

#define REPORT_CHANNEL_ALARMS   1

Definition at line 870 of file chan_dahdi.c.

◆ REPORT_SPAN_ALARMS

#define REPORT_SPAN_ALARMS   2

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

16905 { \
16906 ast_log(LOG_WARNING, "DAHDI channel %d is not FXO signalled\n", p->channel); \
16907 return -1; \
16908 }

◆ sig2str

#define sig2str   dahdi_sig2str

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

Function Documentation

◆ __dahdi_exception()

static struct ast_frame * __dahdi_exception ( struct ast_channel ast)
static

Definition at line 8713 of file chan_dahdi.c.

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

◆ __unload_module()

static int __unload_module ( void  )
static

Definition at line 18411 of file chan_dahdi.c.

18412{
18413 struct dahdi_pvt *p;
18414#if defined(HAVE_PRI) || defined(HAVE_SS7)
18415 int i, j;
18416#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18417
18418#ifdef HAVE_PRI
18419 for (i = 0; i < NUM_SPANS; i++) {
18420 if (pris[i].pri.master != AST_PTHREADT_NULL) {
18421 pthread_cancel(pris[i].pri.master);
18422 pthread_kill(pris[i].pri.master, SIGURG);
18423 }
18424 }
18425 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18426 ast_unregister_application(dahdi_send_keypad_facility_app);
18427#ifdef HAVE_PRI_PROG_W_CAUSE
18428 ast_unregister_application(dahdi_send_callrerouting_facility_app);
18429#endif
18430#endif
18431#if defined(HAVE_SS7)
18432 for (i = 0; i < NUM_SPANS; i++) {
18433 if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
18434 pthread_cancel(linksets[i].ss7.master);
18435 pthread_kill(linksets[i].ss7.master, SIGURG);
18436 }
18437 }
18438 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18439#endif /* defined(HAVE_SS7) */
18440#if defined(HAVE_OPENR2)
18441 dahdi_r2_destroy_links();
18442 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18443 ast_unregister_application(dahdi_accept_r2_call_app);
18444#endif
18445
18448
18450 ast_manager_unregister("DAHDIDialOffhook");
18451 ast_manager_unregister("DAHDIHangup");
18452 ast_manager_unregister("DAHDITransfer");
18453 ast_manager_unregister("DAHDIDNDoff");
18454 ast_manager_unregister("DAHDIDNDon");
18455 ast_manager_unregister("DAHDIShowChannels");
18456 ast_manager_unregister("DAHDIShowStatus");
18457 ast_manager_unregister("DAHDIRestart");
18458#if defined(HAVE_PRI)
18459 ast_manager_unregister("PRIShowSpans");
18460 ast_manager_unregister("PRIDebugSet");
18461 ast_manager_unregister("PRIDebugFileSet");
18462 ast_manager_unregister("PRIDebugFileUnset");
18463#endif /* defined(HAVE_PRI) */
18465
18466 /* Hangup all interfaces if they have an owner */
18468 for (p = iflist; p; p = p->next) {
18469 if (p->owner)
18471 }
18473
18476 pthread_cancel(monitor_thread);
18477 pthread_kill(monitor_thread, SIGURG);
18478 pthread_join(monitor_thread, NULL);
18479 }
18482
18484
18485#if defined(HAVE_PRI)
18486 for (i = 0; i < NUM_SPANS; i++) {
18487 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
18488 pthread_join(pris[i].pri.master, NULL);
18489 }
18490 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
18491 dahdi_close_pri_fd(&(pris[i]), j);
18492 }
18493 sig_pri_stop_pri(&pris[i].pri);
18494 }
18495#if defined(HAVE_PRI_CCSS)
18496 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
18497 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
18498#endif /* defined(HAVE_PRI_CCSS) */
18500#endif
18501
18502#if defined(HAVE_SS7)
18503 for (i = 0; i < NUM_SPANS; i++) {
18504 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
18505 pthread_join(linksets[i].ss7.master, NULL);
18506 }
18507 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
18508 dahdi_close_ss7_fd(&(linksets[i]), j);
18509 }
18510 if (linksets[i].ss7.ss7) {
18511 ss7_destroy(linksets[i].ss7.ss7);
18512 linksets[i].ss7.ss7 = NULL;
18513 }
18514 }
18515#endif /* defined(HAVE_SS7) */
18517
18519
18522 STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
18523 return 0;
18524}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
#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:1222
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition ccss.c:1265
static ast_mutex_t iflock
Protect the interface list (of dahdi_pvt's)
Definition chan_dahdi.c:880
#define NUM_SPANS
Definition chan_dahdi.c:808
static struct dahdi_pvt * iflist
static ast_cond_t ss_thread_complete
Definition chan_dahdi.c:896
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:891
static struct ast_channel_tech dahdi_tech
static struct ast_custom_function dahdichan_function
static struct ast_custom_function polarity_function
static struct ast_cli_entry dahdi_cli[]
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:895
static void destroy_all_channels(void)
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition channel.c:571
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition channel.c:2462
@ AST_SOFTHANGUP_APPUNLOAD
Definition channel.h:1163
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition manager.c:7782
#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:404
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:1546
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:706

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

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

17178{
17179 struct dahdi_pvt *p;
17180 const char *channel = astman_get_header(m, "DAHDIChannel");
17181 const char *number = astman_get_header(m, "Number");
17182 int i;
17183
17184 if (ast_strlen_zero(channel)) {
17185 astman_send_error(s, m, "No channel specified");
17186 return 0;
17187 }
17188 if (ast_strlen_zero(number)) {
17189 astman_send_error(s, m, "No number specified");
17190 return 0;
17191 }
17193 if (!p) {
17194 astman_send_error(s, m, "No such channel");
17195 return 0;
17196 }
17197 if (!p->owner) {
17198 astman_send_error(s, m, "Channel does not have it's owner");
17199 return 0;
17200 }
17201 for (i = 0; i < strlen(number); i++) {
17202 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
17203 dahdi_queue_frame(p, &f);
17204 }
17205 astman_send_ack(s, m, "DAHDIDialOffhook");
17206 return 0;
17207}
static struct dahdi_pvt * find_channel_from_str(const char *channel)
static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition manager.c:1921
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition manager.c:1953
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition manager.c:1582
#define AST_FRAME_DTMF
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
Number structure.

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(), ast_frame_subclass::integer, dahdi_pvt::owner, and ast_frame::subclass.

Referenced by load_module().

◆ action_dahdidndoff()

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

Definition at line 17112 of file chan_dahdi.c.

17113{
17114 struct dahdi_pvt *p;
17115 const char *channel = astman_get_header(m, "DAHDIChannel");
17116
17117 if (ast_strlen_zero(channel)) {
17118 astman_send_error(s, m, "No channel specified");
17119 return 0;
17120 }
17122 if (!p) {
17123 astman_send_error(s, m, "No such channel");
17124 return 0;
17125 }
17126 dahdi_dnd(p, 0);
17127 astman_send_ack(s, m, "DND Disabled");
17128 return 0;
17129}
static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel

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

17094{
17095 struct dahdi_pvt *p;
17096 const char *channel = astman_get_header(m, "DAHDIChannel");
17097
17098 if (ast_strlen_zero(channel)) {
17099 astman_send_error(s, m, "No channel specified");
17100 return 0;
17101 }
17103 if (!p) {
17104 astman_send_error(s, m, "No such channel");
17105 return 0;
17106 }
17107 dahdi_dnd(p, 1);
17108 astman_send_ack(s, m, "DND Enabled");
17109 return 0;
17110}

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

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

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

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

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

17132{
17133 struct dahdi_pvt *p;
17134 const char *channel = astman_get_header(m, "DAHDIChannel");
17135
17136 if (ast_strlen_zero(channel)) {
17137 astman_send_error(s, m, "No channel specified");
17138 return 0;
17139 }
17141 if (!p) {
17142 astman_send_error(s, m, "No such channel");
17143 return 0;
17144 }
17145 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
17146 astman_send_error(s, m, "Channel signaling is not analog");
17147 return 0;
17148 }
17150 astman_send_ack(s, m, "DAHDITransfer");
17151 return 0;
17152}
#define TRANSFER
static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
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 17154 of file chan_dahdi.c.

17155{
17156 struct dahdi_pvt *p;
17157 const char *channel = astman_get_header(m, "DAHDIChannel");
17158
17159 if (ast_strlen_zero(channel)) {
17160 astman_send_error(s, m, "No channel specified");
17161 return 0;
17162 }
17164 if (!p) {
17165 astman_send_error(s, m, "No such channel");
17166 return 0;
17167 }
17168 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
17169 astman_send_error(s, m, "Channel signaling is not analog");
17170 return 0;
17171 }
17173 astman_send_ack(s, m, "DAHDIHangup");
17174 return 0;
17175}
#define HANGUP

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

4687{
4688 int x;
4689 for (x = 0; x < ARRAY_LEN(alarms); x++) {
4690 if (alarms[x].alarm & alm)
4691 return alarms[x].name;
4692 }
4693 return alm ? "Unknown Alarm" : "No Alarm";
4694}
int alarm
static struct @116 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 4481 of file chan_dahdi.c.

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

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

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

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

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

1388{
1389 int index;
1390
1391 switch (analogsub) {
1392 case ANALOG_SUB_REAL:
1393 index = SUB_REAL;
1394 break;
1396 index = SUB_CALLWAIT;
1397 break;
1399 index = SUB_THREEWAY;
1400 break;
1401 default:
1402 ast_log(LOG_ERROR, "Unidentified sub!\n");
1403 index = SUB_REAL;
1404 }
1405
1406 return index;
1407}
@ 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 20768 of file chan_dahdi.c.

◆ attempt_transfer()

static int attempt_transfer ( struct dahdi_pvt p)
static

Definition at line 7572 of file chan_dahdi.c.

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

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

Referenced by dahdi_handle_event().

◆ available()

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

Definition at line 13576 of file chan_dahdi.c.

13577{
13578 struct dahdi_pvt *p = *pvt;
13579
13580 if (p->inalarm)
13581 return 0;
13582
13583 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode))
13584 return analog_available(p->sig_pvt);
13585
13586 switch (p->sig) {
13587#if defined(HAVE_PRI)
13589 {
13590 struct sig_pri_chan *pvt_chan;
13591 int res;
13592
13593 pvt_chan = p->sig_pvt;
13594 res = sig_pri_available(&pvt_chan, is_specific_channel);
13595 *pvt = pvt_chan->chan_pvt;
13596 return res;
13597 }
13598#endif /* defined(HAVE_PRI) */
13599#if defined(HAVE_SS7)
13600 case SIG_SS7:
13601 return sig_ss7_available(p->sig_pvt);
13602#endif /* defined(HAVE_SS7) */
13603 default:
13604 break;
13605 }
13606
13607 if (p->locallyblocked || p->remotelyblocked) {
13608 return 0;
13609 }
13610
13611 /* If no owner definitely available */
13612 if (!p->owner) {
13613#ifdef HAVE_OPENR2
13614 /* Trust MFC/R2 */
13615 if (p->mfcr2) {
13616 if (p->mfcr2call) {
13617 return 0;
13618 } else {
13619 return 1;
13620 }
13621 }
13622#endif
13623 return 1;
13624 }
13625
13626 return 0;
13627}
#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:803
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 16412 of file chan_dahdi.c.

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

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

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

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

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

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

Referenced by analog_ss_thread().

◆ check_for_conference()

static int check_for_conference ( struct dahdi_pvt p)
static

Definition at line 7605 of file chan_dahdi.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4448{
4449 if (fd > 0)
4450 close(fd);
4451}

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

4454{
4455 dahdi_close(chan_pvt->subs[sub_num].dfd);
4456 chan_pvt->subs[sub_num].dfd = -1;
4457}
static void dahdi_close(int fd)

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

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

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

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

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

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

11541{
11542 struct dahdi_pvt *cur;
11543 struct dahdi_pvt *next;
11544 int destroyed_first = 0;
11545 int destroyed_last = 0;
11546
11548 ast_debug(1, "range: %d-%d\n", start, end);
11549 for (cur = iflist; cur; cur = next) {
11550 next = cur->next;
11551 if (cur->channel >= start && cur->channel <= end) {
11552 int x = DAHDI_FLASH;
11553
11554 if (cur->channel > destroyed_last) {
11555 destroyed_last = cur->channel;
11556 }
11557 if (destroyed_first < 1 || cur->channel < destroyed_first) {
11558 destroyed_first = cur->channel;
11559 }
11560 ast_debug(3, "Destroying %d\n", cur->channel);
11561 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11562 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11563
11564 destroy_channel(cur, 1);
11566 }
11567 }
11569 if (destroyed_first > start || destroyed_last < end) {
11570 ast_debug(1, "Asked to destroy %d-%d, destroyed %d-%d,\n",
11571 start, end, destroyed_first, destroyed_last);
11572 }
11573}
static void destroy_channel(struct dahdi_pvt *cur, int now)
#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 15823 of file chan_dahdi.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

8836{
8837 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8838 struct ast_frame *f;
8839 ast_mutex_lock(&p->lock);
8840 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8841 struct analog_pvt *analog_p = p->sig_pvt;
8842 f = analog_exception(analog_p, ast);
8843 } else {
8844 f = __dahdi_exception(ast);
8845 }
8847 return f;
8848}
static struct ast_frame * __dahdi_exception(struct ast_channel *ast)
struct ast_frame * analog_exception(struct analog_pvt *p, struct ast_channel *ast)

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

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

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

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

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

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

908{
909 int j;
910 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
911 return -1;
912 return j;
913}

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

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

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

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

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

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

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

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

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

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

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

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

9617{
9618 struct ast_channel *tmp;
9619 struct ast_format_cap *caps;
9620 struct ast_format *deflaw;
9621 int x;
9622 int features;
9623 struct ast_str *chan_name;
9624 struct ast_variable *v;
9625 char *dashptr;
9626 char device_name[AST_CHANNEL_NAME];
9627
9628 if (i->subs[idx].owner) {
9629 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
9630 return NULL;
9631 }
9632
9633#if defined(HAVE_PRI)
9634 /*
9635 * The dnid has been stuffed with the called-number[:subaddress]
9636 * by dahdi_request() for outgoing calls.
9637 */
9638 chan_name = create_channel_name(i, i->outgoing, i->dnid);
9639#else
9640 chan_name = create_channel_name(i);
9641#endif /* defined(HAVE_PRI) */
9642 if (!chan_name) {
9643 return NULL;
9644 }
9645
9647 if (!caps) {
9648 ast_free(chan_name);
9649 return NULL;
9650 }
9651
9652 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));
9653 ast_free(chan_name);
9654 if (!tmp) {
9655 ao2_ref(caps, -1);
9656 return NULL;
9657 }
9658
9660
9661 if (callid) {
9662 ast_channel_callid_set(tmp, callid);
9663 }
9664
9666#if defined(HAVE_PRI)
9667 if (i->pri) {
9669 }
9670#endif /* defined(HAVE_PRI) */
9672 if (law) {
9673 i->law = law;
9674 if (law == DAHDI_LAW_ALAW) {
9675 deflaw = ast_format_alaw;
9676 } else {
9677 deflaw = ast_format_ulaw;
9678 }
9679 } else {
9680 switch (i->sig) {
9682 /* Make sure companding law is known. */
9683 i->law = (i->law_default == DAHDI_LAW_ALAW)
9684 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
9685 break;
9686 default:
9687 i->law = i->law_default;
9688 break;
9689 }
9690 if (i->law_default == DAHDI_LAW_ALAW) {
9691 deflaw = ast_format_alaw;
9692 } else {
9693 deflaw = ast_format_ulaw;
9694 }
9695 }
9696 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
9697 ast_format_cap_append(caps, deflaw, 0);
9699 ao2_ref(caps, -1);
9700 /* Start out assuming ulaw since it's smaller :) */
9701 ast_channel_set_rawreadformat(tmp, deflaw);
9702 ast_channel_set_readformat(tmp, deflaw);
9703 ast_channel_set_rawwriteformat(tmp, deflaw);
9704 ast_channel_set_writeformat(tmp, deflaw);
9705 i->subs[idx].linear = 0;
9706 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
9707 features = 0;
9708 if (idx == SUB_REAL) {
9709 if (i->busydetect && CANBUSYDETECT(i))
9710 features |= DSP_FEATURE_BUSY_DETECT;
9712 features |= DSP_FEATURE_CALL_PROGRESS;
9714 features |= DSP_FEATURE_WAITDIALTONE;
9715 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
9717 features |= DSP_FEATURE_FAX_DETECT;
9718 }
9719 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
9720 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
9721 i->hardwaredtmf = 0;
9722 features |= DSP_FEATURE_DIGIT_DETECT;
9723 } else if (NEED_MFDETECT(i)) {
9724 i->hardwaredtmf = 1;
9725 features |= DSP_FEATURE_DIGIT_DETECT;
9726 }
9727 }
9728 if (features) {
9729 if (i->dsp) {
9730 ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
9731 } else {
9732 if (i->channel != CHAN_PSEUDO)
9733 i->dsp = ast_dsp_new();
9734 else
9735 i->dsp = NULL;
9736 if (i->dsp) {
9737 i->dsp_features = features;
9738#if defined(HAVE_PRI) || defined(HAVE_SS7)
9739 /* We cannot do progress detection until receive PROGRESS message */
9740 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
9741 /* Remember requested DSP features, don't treat
9742 talking as ANSWER */
9743 i->dsp_features = features & ~DSP_PROGRESS_TALK;
9744 features = 0;
9745 }
9746#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9747 ast_dsp_set_features(i->dsp, features);
9751 if (i->busydetect && CANBUSYDETECT(i)) {
9754 }
9755 }
9756 }
9757 }
9758
9760
9761 if (state == AST_STATE_RING)
9762 ast_channel_rings_set(tmp, 1);
9764 if (IS_FXO_SIG(i)) {
9765 /* Only FXO signalled stuff can be picked up */
9770 }
9771 if (!ast_strlen_zero(i->parkinglot))
9772 ast_channel_parkinglot_set(tmp, i->parkinglot);
9773 if (!ast_strlen_zero(i->language))
9774 ast_channel_language_set(tmp, i->language);
9775 if (!i->owner)
9776 i->owner = tmp;
9778 ast_channel_accountcode_set(tmp, i->accountcode);
9779 if (i->amaflags)
9781 i->subs[idx].owner = tmp;
9783 if (!dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
9784 ast_channel_call_forward_set(tmp, i->call_forward);
9785 }
9786 /* If we've been told "no ADSI" then enforce it */
9787 if (!i->adsi)
9789 if (!ast_strlen_zero(i->exten))
9791 if (!ast_strlen_zero(i->rdnis)) {
9794 }
9795 if (!ast_strlen_zero(i->dnid)) {
9797 }
9798
9799 /* Don't use ast_set_callerid() here because it will
9800 * generate a needless NewCallerID event */
9801#if defined(HAVE_PRI) || defined(HAVE_SS7)
9802 if (!ast_strlen_zero(i->cid_ani)) {
9804 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_ani);
9805 } else if (!ast_strlen_zero(i->cid_num)) {
9808 }
9809#else
9810 if (!ast_strlen_zero(i->cid_num)) {
9813 }
9814#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9818 ast_channel_caller(tmp)->ani2 = i->cid_ani2;
9820 /* clear the fake event in case we posted one before we had ast_channel */
9821 i->fake_event = 0;
9822 /* Assure there is no confmute on this channel */
9823 dahdi_confmute(i, 0);
9824 i->muting = 0;
9825 /* Configure the new channel jb */
9827
9828 /* Set initial device state */
9829 if (IS_FXO_SIG(i) && idx == SUB_REAL && state == AST_STATE_RESERVED && !startpbx && requestor) {
9830 /* In the case that an analog line is receiving a call, temporarily suppress device state updates.
9831 * If we updated the device state right now, the calculated device state would be "INUSE",
9832 * even though almost instantly, it will become "RINGING". This is problematic,
9833 * because many IP phones ignore INUSE -> RINGING transitions since that's not technically possible.
9834 * To prevent such a bogus transition, if this line is about to ring and is not already in use, skip the update.
9835 * The next update will correctly start device state at RINGING so everything works as devices expect. */
9836 ast_debug(3, "Suppressing immediate device state update to prevent INUSE -> RINGING transition\n");
9837 } else {
9838 ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
9839 dashptr = strrchr(device_name, '-');
9840 if (dashptr) {
9841 *dashptr = '\0';
9842 }
9844 }
9845
9846 for (v = i->vars ; v ; v = v->next)
9848
9850
9851 ast_channel_unlock(tmp);
9852
9854
9856 if (startpbx) {
9857#ifdef HAVE_OPENR2
9858 if (i->mfcr2call) {
9859 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
9860 }
9861#endif
9862 if (ast_pbx_start(tmp)) {
9863 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
9864 ast_hangup(tmp);
9865 return NULL;
9866 }
9867 }
9868 return tmp;
9869}
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
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:876
#define CALLPROGRESS_FAX_INCOMING
Definition chan_dahdi.c:815
#define CALLPROGRESS_FAX_OUTGOING
Definition chan_dahdi.c:814
static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
static struct ast_jb_conf global_jbconf
Definition chan_dahdi.c:756
static char progzone[10]
Definition chan_dahdi.c:860
#define CANBUSYDETECT(p)
Definition chan_dahdi.c:848
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:10627
@ 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:2417
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_CACHABLE
Definition devicestate.h:70
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.
#define DSP_FEATURE_WAITDIALTONE
Definition dsp.h:46
#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:1989
#define DSP_FEATURE_FAX_DETECT
Definition dsp.h:29
#define DSP_FEATURE_CALL_PROGRESS
Definition dsp.h:45
void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
Set number of required cadences for busy.
Definition dsp.c:1978
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition dsp.c:1943
int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
Set zone for doing progress detection.
Definition dsp.c:2079
struct ast_format * ast_format_alaw
Built-in cached alaw format.
@ 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:3268
Format capabilities structure, holds formats + preference order + etc.
Definition format_cap.c:54
Definition of a media format.
Definition format.c:43
struct ast_party_dialed::@218 number
Dialed/Called number.
char * str
Subscriber phone number (Malloced)
Definition channel.h:388
char * tag
User-set "tag".
Definition channel.h:356
int presentation
Q.931 encoded presentation-indicator encoded field.
Definition channel.h:279
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition channel.h:297
int plan
Q.931 Type-Of-Number and Numbering-Plan encoded fields.
Definition channel.h:295
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition channel.h:529
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
struct ast_variable * vars
Channel variable list with associated values to set when a channel is created.
Definition chan_dahdi.h:590
int busycount
Number of times to see "busy" tone before hanging up.
Definition chan_dahdi.h:647
int waitfordialtone
Number of milliseconds to wait for dialtone.
Definition chan_dahdi.h:662
unsigned int adsi
TRUE if ADSI (Analog Display Services Interface) available.
Definition chan_dahdi.h:178
int dialtone_scanning_time_elapsed
Definition chan_dahdi.h:676
char dnid[AST_MAX_EXTENSION]
Dialed Number Identifier.
Definition chan_dahdi.h:553
struct ast_namedgroups * named_pickupgroups
Named pickup groups this belongs to.
Definition chan_dahdi.h:585
int cid_ani2
Automatic Number Identification code from PRI.
Definition chan_dahdi.h:530
struct ast_namedgroups * named_callgroups
Named call groups this belongs to.
Definition chan_dahdi.h:580
unsigned int busydetect
TRUE if busy detection is enabled. (Listens for the beep-beep busy pattern.)
Definition chan_dahdi.h:206
ast_group_t pickupgroup
Bitmapped pickup groups this belongs to.
Definition chan_dahdi.h:575
int callingpres
Definition chan_dahdi.h:598
char parkinglot[AST_MAX_EXTENSION]
Definition chan_dahdi.h:524
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_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_CACHABLE, ast_devstate_changed_literal(), ast_dsp_new(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_digitmode(), ast_dsp_set_features(), ast_format_alaw, ast_format_cap_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_STATE_RESERVED, 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, IS_FXO_SIG, 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_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 9607 of file chan_dahdi.c.

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

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

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

3804{
3805 for (;;) {
3806 if (p->owner) {
3807 if (ast_channel_trylock(p->owner)) {
3809 } else {
3810 ast_queue_frame(p->owner, f);
3812 break;
3813 }
3814 } else
3815 break;
3816 }
3817}
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:1171

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4476{
4477 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
4478}

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

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

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

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

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

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

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

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

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

15917{
15918 struct dahdi_pvt *p;
15919retry:
15921 for (p = iflist; p; p = p->next) {
15922 ast_mutex_lock(&p->lock);
15923 if (p->owner && !p->restartpending) {
15924 if (ast_channel_trylock(p->owner)) {
15925 if (DEBUG_ATLEAST(3))
15926 ast_verbose("Avoiding deadlock\n");
15927 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15930 goto retry;
15931 }
15932 if (DEBUG_ATLEAST(3))
15933 ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15935 p->restartpending = 1;
15938 }
15940 }
15942}
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition channel.c:2449
#define DEBUG_ATLEAST(level)
#define ast_verbose(...)

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

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

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

917{
918 int i, j = 0;
919 i = DAHDI_IOMUX_SIGEVENT;
920 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
921 return -1;
922 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
923 return -1;
924 return j;
925}

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

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

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

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

16986{
16987 char *parse;
16988 struct dahdi_pvt *pvt;
16989 struct dahdi_params dahdip;
16990 int res;
16992 AST_APP_ARG(property);
16993 AST_APP_ARG(dahdichan);
16994 );
16995
16996 parse = ast_strdupa(data);
16998
16999 if (buflen > 0) {
17000 *buffer = '\0';
17001 }
17002
17003 if (!ast_strlen_zero(args.dahdichan)) {
17004 /* DAHDI channel number explicitly provided, find it. */
17005 int channo = atoi(args.dahdichan);
17006 pvt = find_channel(channo);
17007 if (!pvt) {
17008 ast_log(LOG_ERROR, "DAHDI channel %d does not exist\n", channo);
17009 return -1;
17010 }
17011 } else {
17012 /* No channel specified explicitly, so implicitly use the current channel, in which case it must be a DAHDI channel. */
17013 if (!chan || !ast_channel_tech(chan) || strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
17014 ast_log(LOG_WARNING, "%s is not a DAHDI channel, and no DAHDI channel specified\n", ast_channel_name(chan));
17015 return -1;
17016 }
17017 pvt = ast_channel_tech_pvt(chan);
17018 }
17019
17020 memset(&dahdip, 0, sizeof(dahdip));
17021 if (ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &dahdip)) {
17022 ast_log(LOG_WARNING, "Unable to get parameters of DAHDI channel %d: %s\n", pvt->channel, strerror(errno));
17023 return -1;
17024 }
17025
17026 /* We have the channel private to use. */
17027 ast_mutex_lock(&pvt->lock);
17028 if (value) {
17029 res = dahdichan_write_property(pvt, &dahdip, args.property, value);
17030 } else {
17031 res = dahdichan_read_property(pvt, &dahdip, args.property, buffer, buflen);
17032 }
17033 ast_mutex_unlock(&pvt->lock);
17034 return res;
17035}
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_property(struct dahdi_pvt *p, struct dahdi_params *dahdip, const char *property, const char *value)
static struct dahdi_pvt * find_channel(int channel)
#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_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 17037 of file chan_dahdi.c.

17038{
17039 return dahdichan_helper(chan, data, NULL, buffer, buflen);
17040}
static int dahdichan_helper(struct ast_channel *chan, char *data, const char *value, char *buffer, size_t buflen)

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

16911{
16912 struct analog_pvt *analog_p = p->sig_pvt;
16913
16914 /* R/O properties */
16915 if (!strcasecmp(property, "owner")) {
16916 return print_subchannel(p, SUB_REAL, buffer, len);
16917 } else if (!strcasecmp(property, "callwait")) {
16918 return print_subchannel(p, SUB_CALLWAIT, buffer, len);
16919 } else if (!strcasecmp(property, "threeway")) {
16920 return print_subchannel(p, SUB_THREEWAY, buffer, len);
16921 /* R/W properties */
16922 } else if (!strcasecmp(property, "polarity")) {
16924 snprintf(buffer, len, "%d", p->polarity);
16925 } else if (!strcasecmp(property, "dnd")) {
16927 snprintf(buffer, len, "%d", analog_p->dnd);
16928 } else if (!strcasecmp(property, "callforward")) {
16930 snprintf(buffer, len, "%s", analog_p->call_forward);
16931 } else if (!strcasecmp(property, "lastexten")) {
16933 snprintf(buffer, len, "%s", analog_p->lastexten);
16934 } else {
16935 ast_log(LOG_ERROR, "Unknown DAHDI_CHANNEL property '%s'\n", property);
16936 return -1;
16937 }
16938 return 0;
16939}
#define REQUIRE_FXO_SIG()
static int print_subchannel(struct dahdi_pvt *p, int subchan, char *buffer, size_t len)
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 17042 of file chan_dahdi.c.

17043{
17044 return dahdichan_helper(chan, data, value, NULL, 0);
17045}

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

16942{
16943 struct analog_pvt *analog_p = p->sig_pvt;
16944
16945 /* We don't need to check ast_strlen_zero(value) because it's obviously not NULL.
16946 * It may even be okay for it to be an empty string, but that's a per-setting thing. */
16947
16948 /* R/O properties */
16949 if (!strcasecmp(property, "owner") || !strcasecmp(property, "callwait") || !strcasecmp(property, "threeway")) {
16950 ast_log(LOG_ERROR, "DAHDI subchannel names are R/O\n");
16951 return -1;
16952 /* R/W properties */
16953 } else if (!strcasecmp(property, "polarity")) {
16954 int polarity = atoi(value);
16957 ast_log(LOG_ERROR, "Invalid polarity: '%s'\n", value);
16958 return -1;
16959 }
16961 } else if (!strcasecmp(property, "dnd")) {
16962 int dnd = atoi(value);
16964 analog_dnd(analog_p, dnd ? 1 : 0);
16965 } else if (!strcasecmp(property, "callforward")) {
16967 if (strlen(value) >= sizeof(analog_p->call_forward) - 1) {
16968 ast_log(LOG_ERROR, "Provided call forwarding target '%s' is too long\n", value);
16969 }
16970 ast_copy_string(analog_p->call_forward, value, sizeof(analog_p->call_forward)); /* Could be empty to clear value */
16971 } else if (!strcasecmp(property, "lastexten")) {
16973 if (strlen(value) >= sizeof(analog_p->lastexten) - 1) {
16974 ast_log(LOG_ERROR, "Provided lastexten target '%s' is too long\n", value);
16975 }
16976 ast_copy_string(analog_p->lastexten, value, sizeof(analog_p->lastexten)); /* Could be empty to clear value */
16977 } else {
16978 ast_log(LOG_ERROR, "Unknown DAHDI_CHANNEL property '%s'\n", property);
16979 return -1;
16980 }
16981 return 0;
16982}
static void my_set_polarity(void *pvt, int value)

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

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

2741{
2742 enum analog_event res;
2743
2744 switch (event) {
2745 case DAHDI_EVENT_ONHOOK:
2746 res = ANALOG_EVENT_ONHOOK;
2747 break;
2748 case DAHDI_EVENT_RINGOFFHOOK:
2750 break;
2751 case DAHDI_EVENT_WINKFLASH:
2753 break;
2754 case DAHDI_EVENT_ALARM:
2755 res = ANALOG_EVENT_ALARM;
2756 break;
2757 case DAHDI_EVENT_NOALARM:
2759 break;
2760 case DAHDI_EVENT_DIALCOMPLETE:
2762 break;
2763 case DAHDI_EVENT_RINGERON:
2765 break;
2766 case DAHDI_EVENT_RINGEROFF:
2768 break;
2769 case DAHDI_EVENT_HOOKCOMPLETE:
2771 break;
2772 case DAHDI_EVENT_PULSE_START:
2774 break;
2775 case DAHDI_EVENT_POLARITY:
2777 break;
2778 case DAHDI_EVENT_RINGBEGIN:
2780 break;
2781 case DAHDI_EVENT_EC_DISABLED:
2783 break;
2784 case DAHDI_EVENT_REMOVED:
2786 break;
2787 case DAHDI_EVENT_NEONMWI_ACTIVE:
2789 break;
2790 case DAHDI_EVENT_NEONMWI_INACTIVE:
2792 break;
2793#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
2794 case DAHDI_EVENT_TX_CED_DETECTED:
2796 break;
2797 case DAHDI_EVENT_RX_CED_DETECTED:
2799 break;
2800 case DAHDI_EVENT_EC_NLP_DISABLED:
2802 break;
2803 case DAHDI_EVENT_EC_NLP_ENABLED:
2805 break;
2806#endif
2807 case DAHDI_EVENT_PULSEDIGIT:
2809 break;
2810 case DAHDI_EVENT_DTMFDOWN:
2812 break;
2813 case DAHDI_EVENT_DTMFUP:
2814 res = ANALOG_EVENT_DTMFUP;
2815 break;
2816 default:
2817 switch(event & 0xFFFF0000) {
2818 case DAHDI_EVENT_PULSEDIGIT:
2819 case DAHDI_EVENT_DTMFDOWN:
2820 case DAHDI_EVENT_DTMFUP:
2821 /* The event includes a digit number in the low word.
2822 * Converting it to a 'enum analog_event' would remove
2823 * that information. Thus it is returned as-is.
2824 */
2825 return event;
2826 }
2827
2828 res = ANALOG_EVENT_ERROR;
2829 break;
2830 }
2831
2832 return res;
2833}
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

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

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

20232{
20233 struct ast_cc_config_params *cc_params;
20234
20235 cc_params = dest->chan.cc_params;
20236 *dest = *src;
20237 dest->chan.cc_params = cc_params;
20239}

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

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

Referenced by __unload_module(), and dahdi_restart().

◆ destroy_channel()

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

Definition at line 5961 of file chan_dahdi.c.

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

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

5882{
5883 struct dahdi_pvt *p = pvt;
5884
5885 if (p->manages_span_alarms) {
5887 if (next) {
5889 }
5890 }
5891
5892 /* Remove channel from the list */
5893#if defined(HAVE_PRI)
5894 dahdi_unlink_pri_pvt(p);
5895#endif /* defined(HAVE_PRI) */
5896#if defined(HAVE_SS7)
5897 dahdi_unlink_ss7_pvt(p);
5898#endif /* defined(HAVE_SS7) */
5899#if defined(HAVE_OPENR2)
5900 dahdi_unlink_mfcr2_pvt(p);
5901#endif /* defined(HAVE_SS7) */
5902 switch (pvt->which_iflist) {
5903 case DAHDI_IFLIST_NONE:
5904 break;
5905 case DAHDI_IFLIST_MAIN:
5907 break;
5908#if defined(HAVE_PRI)
5909 case DAHDI_IFLIST_NO_B_CHAN:
5910 if (p->pri) {
5911 dahdi_nobch_extract(p->pri, p);
5912 }
5913 break;
5914#endif /* defined(HAVE_PRI) */
5915 }
5916
5917 if (p->sig_pvt) {
5918 if (dahdi_analog_lib_handles(p->sig, 0, 0)) {
5920 }
5921 switch (p->sig) {
5922#if defined(HAVE_PRI)
5925 break;
5926#endif /* defined(HAVE_PRI) */
5927#if defined(HAVE_SS7)
5928 case SIG_SS7:
5930 break;
5931#endif /* defined(HAVE_SS7) */
5932 default:
5933 break;
5934 }
5935 }
5936 ast_free(p->cidspill);
5937 if (p->use_smdi) {
5939 }
5940 if (p->mwi_event_sub) {
5942 }
5943 if (p->vars) {
5945 }
5946 if (p->cc_params) {
5948 }
5949
5952
5955 if (p->owner) {
5957 }
5958 ast_free(p);
5959}
static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
static struct dahdi_pvt * find_next_iface_in_span(struct dahdi_pvt *cur)
struct ast_namedgroups * ast_unref_namedgroups(struct ast_namedgroups *groups)
Definition channel.c:7768
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.
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 13846 of file chan_dahdi.c.

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

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_pvt::group, 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 4535 of file chan_dahdi.c.

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

References digit.

Referenced by dahdi_digit_begin().

◆ do_monitor()

static void * do_monitor ( void *  data)
static

Definition at line 11954 of file chan_dahdi.c.

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

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

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

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

4697{
4698 static char buf[256];
4699 if ((event > -1) && (event < (ARRAY_LEN(events))) )
4700 return events[event];
4701 sprintf(buf, "Event %d", event); /* safe */
4702 return buf;
4703}
static const char *const events[]

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

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

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

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

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

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

16882{
16883 int chan_num;
16884
16885 if (sscanf(channel, "%30d", &chan_num) != 1) {
16886 /* Not numeric string. */
16887 return NULL;
16888 }
16889
16890 return find_channel(chan_num);
16891}

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

5871{
5872 if (cur->next && cur->next->span == cur->span) {
5873 return cur->next;
5874 } else if (cur->prev && cur->prev->span == cur->span) {
5875 return cur->prev;
5876 }
5877
5878 return NULL;
5879}

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

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

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

7792{
7793 const char *alarm_str;
7794
7795#if defined(HAVE_PRI)
7797 return;
7798 }
7799#endif /* defined(HAVE_PRI) */
7800
7801 alarm_str = alarm2str(alms);
7803 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
7804 publish_channel_alarm(p->channel, alarm_str);
7805 }
7806
7808 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
7809 publish_span_alarm(p->span, alarm_str);
7810 }
7811}
static void publish_channel_alarm(int channel, const char *alarm_txt)
static void publish_span_alarm(int span, const char *alarm_txt)
static int report_alarms
Definition chan_dahdi.c:872
#define REPORT_CHANNEL_ALARMS
Definition chan_dahdi.c:870
#define REPORT_SPAN_ALARMS
Definition chan_dahdi.c:871
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 3850 of file chan_dahdi.c.

3851{
3852#if defined(HAVE_PRI)
3854 return;
3855 }
3856#endif /* defined(HAVE_PRI) */
3857
3860 }
3863 }
3864}
static void publish_channel_alarm_clear(int channel)
static void publish_span_alarm_clear(int span)

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

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

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

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

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

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

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

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

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

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

20514{
20515 int res;
20516#if defined(HAVE_PRI) || defined(HAVE_SS7)
20517 int y;
20518#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
20519
20520 if (STASIS_MESSAGE_TYPE_INIT(dahdichannel_type)) {
20522 }
20523
20526 }
20530
20534 }
20535
20536#ifdef HAVE_PRI
20537 memset(pris, 0, sizeof(pris));
20538 for (y = 0; y < NUM_SPANS; y++) {
20539 sig_pri_init_pri(&pris[y].pri);
20540 }
20541 pri_set_error(dahdi_pri_error);
20542 pri_set_message(dahdi_pri_message);
20543 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
20544#ifdef HAVE_PRI_PROG_W_CAUSE
20545 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
20546#endif
20547#if defined(HAVE_PRI_CCSS)
20548 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
20549 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
20552 }
20553#endif /* defined(HAVE_PRI_CCSS) */
20554 if (sig_pri_load(
20555#if defined(HAVE_PRI_CCSS)
20556 dahdi_pri_cc_type
20557#else
20558 NULL
20559#endif /* defined(HAVE_PRI_CCSS) */
20560 )) {
20563 }
20564#endif
20565#if defined(HAVE_SS7)
20566 memset(linksets, 0, sizeof(linksets));
20567 for (y = 0; y < NUM_SPANS; y++) {
20568 sig_ss7_init_linkset(&linksets[y].ss7);
20569 }
20570 ss7_set_error(dahdi_ss7_error);
20571 ss7_set_message(dahdi_ss7_message);
20572 ss7_set_hangup(sig_ss7_cb_hangup);
20573 ss7_set_notinservice(sig_ss7_cb_notinservice);
20574 ss7_set_call_null(sig_ss7_cb_call_null);
20575#endif /* defined(HAVE_SS7) */
20576 res = setup_dahdi(0);
20577 /* Make sure we can register our DAHDI channel type */
20578 if (res) {
20581 }
20583 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
20586 }
20587#ifdef HAVE_PRI
20588 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
20589#endif
20590#if defined(HAVE_SS7)
20591 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
20592#endif /* defined(HAVE_SS7) */
20593#ifdef HAVE_OPENR2
20594 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
20595 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
20596#endif
20597
20600
20602 memset(round_robin, 0, sizeof(round_robin));
20603 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
20605 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
20608 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
20609 ast_manager_register_xml("DAHDIShowStatus", 0, action_dahdishowstatus);
20611#if defined(HAVE_PRI)
20612 ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
20613 ast_manager_register_xml("PRIDebugSet", 0, action_pri_debug_set);
20614 ast_manager_register_xml("PRIDebugFileSet", EVENT_FLAG_SYSTEM, action_pri_debug_file_set);
20615 ast_manager_register_xml("PRIDebugFileUnset", 0, action_pri_debug_file_unset);
20616#endif /* defined(HAVE_PRI) */
20617
20619
20620 return res;
20621}
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:1186
int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
Register a set of agent callbacks with the core.
Definition ccss.c:1247
static int __unload_module(void)
static int action_transfer(struct mansession *s, const struct message *m)
static int action_dahdidndon(struct mansession *s, const struct message *m)
static int action_dahdishowchannels(struct mansession *s, const struct message *m)
static int action_dahdirestart(struct mansession *s, const struct message *m)
static int action_dahdidndoff(struct mansession *s, const struct message *m)
static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
static int action_transferhangup(struct mansession *s, const struct message *m)
static int action_dahdishowstatus(struct mansession *s, const struct message *m)
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:540
#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:193
@ 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:1563
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:1524

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

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

11949 {
11950 struct pollfd **pfds = arg;
11951 ast_free(*pfds);
11952}

References ast_free.

Referenced by do_monitor().

◆ mwi_send_init()

static int mwi_send_init ( struct dahdi_pvt pvt)
static

Definition at line 11355 of file chan_dahdi.c.

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

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

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

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

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

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

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

2715{
2716 struct dahdi_pvt *p = pvt;
2717
2718 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
2719}
static int analogsub_to_dahdisub(enum analog_sub analogsub)

References alloc_sub(), and analogsub_to_dahdisub().

◆ my_answer_polarityswitch()

static void my_answer_polarityswitch ( void *  pvt)
static

Definition at line 2949 of file chan_dahdi.c.

2950{
2951 struct dahdi_pvt *p = pvt;
2952
2953 if (!p->answeronpolarityswitch) {
2954 return;
2955 }
2956
2957 my_set_polarity(pvt, 1);
2958}

References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().

◆ my_callwait()

static int my_callwait ( void *  pvt)
static

Definition at line 1798 of file chan_dahdi.c.

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

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

2348{
2349 struct dahdi_pvt *p = pvt;
2350
2351 ast_free(p->cidspill);
2352 p->cidspill = NULL;
2354}

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

◆ my_check_confirmanswer()

static int my_check_confirmanswer ( void *  pvt)
static

Definition at line 2330 of file chan_dahdi.c.

2331{
2332 struct dahdi_pvt *p = pvt;
2333 if (p->confirmanswer) {
2334 return 1;
2335 }
2336
2337 return 0;
2338}

References dahdi_pvt::confirmanswer.

◆ my_check_for_conference()

static int my_check_for_conference ( void *  pvt)
static

Definition at line 2507 of file chan_dahdi.c.

2508{
2509 struct dahdi_pvt *p = pvt;
2510 return check_for_conference(p);
2511}

References check_for_conference().

◆ my_check_waitingfordt()

static int my_check_waitingfordt ( void *  pvt)
static

Definition at line 2313 of file chan_dahdi.c.

2314{
2315 struct dahdi_pvt *p = pvt;
2316
2317 if (p->waitingfordt.tv_sec) {
2318 return 1;
2319 }
2320
2321 return 0;
2322}

References dahdi_pvt::waitingfordt.

◆ my_complete_conference_update()

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

Definition at line 2457 of file chan_dahdi.c.

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

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

2448{
2449 struct dahdi_pvt *p = pvt;
2450 int x = analogsub_to_dahdisub(sub);
2451
2452 return conf_add(p, &p->subs[x], x, 0);
2453}
static struct stasis_subscription * sub
Statsd channel stats. Exmaple of how to subscribe to Stasis events.

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

2438{
2439 struct dahdi_pvt *p = pvt;
2440 int x = analogsub_to_dahdisub(sub);
2441
2442 return conf_del(p, &p->subs[x], x);
2443}

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

2357{
2358 struct dahdi_pvt *p = pvt;
2359 return dahdi_confmute(p, mute);
2360}

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

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

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

2038{
2039 struct dahdi_pvt *p = pvt;
2040
2042}

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

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

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

1886{
1887 struct dahdi_pvt *p = pvt;
1888 if (p->dsp)
1890
1891 return 0;
1892}

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

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

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

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

2162{
2163 int res;
2164 struct dahdi_pvt *p = pvt;
2165
2166 res = get_alarms(p);
2167 handle_alarms(p, res);
2168}

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

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

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

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

2376{
2377 struct dahdi_pvt *p = pvt;
2378
2379 return p->dialstring;
2380}

References dahdi_pvt::dialstring.

◆ my_get_sigpvt_bridged_channel()

static void * my_get_sigpvt_bridged_channel ( struct ast_channel chan)
static

Definition at line 2170 of file chan_dahdi.c.

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

References ast_channel_bridge_peer(), ast_channel_cleanup, 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 2184 of file chan_dahdi.c.

2185{
2186 struct dahdi_pvt *p = pvt;
2187 int dahdi_sub = analogsub_to_dahdisub(sub);
2188 return p->subs[dahdi_sub].dfd;
2189}

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

9873{
9874 char c;
9875
9876 *str = 0; /* start with empty output buffer */
9877 for (;;)
9878 {
9879 /* Wait for the first digit (up to specified ms). */
9880 c = ast_waitfordigit(chan, ms);
9881 /* if timeout, hangup or error, return as such */
9882 if (c < 1)
9883 return c;
9884 *str++ = c;
9885 *str = 0;
9886 if (strchr(term, c))
9887 return 1;
9888 }
9889}
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 1951 of file chan_dahdi.c.

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

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

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

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

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

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

2724{
2725 struct dahdi_pvt *p = pvt;
2726
2727 return has_voicemail(p);
2728}

References has_voicemail().

◆ my_have_progressdetect()

static int my_have_progressdetect ( void *  pvt)
static

Definition at line 3644 of file chan_dahdi.c.

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

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

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

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

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

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

2026{
2027 struct dahdi_pvt *p = pvt;
2028 ast_mutex_lock(&p->lock);
2029}

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

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

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

2918{
2919 struct dahdi_pvt *p = pvt;
2920 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2921}

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

3029{
3030 struct dahdi_pvt *p = pvt;
3031 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
3032}

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

2731{
2732 struct dahdi_pvt *p = pvt;
2733 int index;
2734
2735 index = analogsub_to_dahdisub(sub);
2736
2737 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
2738}
static int analog_tone_to_dahditone(enum analog_tone tone)

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

2902{
2903 struct dahdi_pvt *p = pvt;
2904
2905 return dahdi_ring_phone(p);
2906}

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

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

2211{
2212 struct dahdi_pvt *p = pvt;
2213
2214 p->inalarm = in_alarm;
2215}

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

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

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

2341{
2342 struct dahdi_pvt *p = pvt;
2343
2344 p->callwaiting = callwaiting_enable;
2345}

References dahdi_pvt::callwaiting.

◆ my_set_confirmanswer()

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

Definition at line 2324 of file chan_dahdi.c.

2325{
2326 struct dahdi_pvt *p = pvt;
2327 p->confirmanswer = flag;
2328}

References dahdi_pvt::confirmanswer.

◆ my_set_dialing()

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

Definition at line 2217 of file chan_dahdi.c.

2218{
2219 struct dahdi_pvt *p = pvt;
2220
2221 p->dialing = is_dialing;
2222}

References dahdi_pvt::dialing.

◆ my_set_echocanceller()

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

Definition at line 2887 of file chan_dahdi.c.

2888{
2889 struct dahdi_pvt *p = pvt;
2890
2891 if (enable)
2892 dahdi_ec_enable(p);
2893 else
2895
2896 return 0;
2897}

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

2152{
2153 struct dahdi_pvt *p = pvt;
2154 int idx = analogsub_to_dahdisub(sub);
2155
2156 p->subs[idx].inthreeway = inthreeway;
2157}

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

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

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

2924{
2925 struct dahdi_pvt *p = pvt;
2927}

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

2369{
2370 struct dahdi_pvt *p = pvt;
2371
2372 p->owner = new_owner;
2373}

References dahdi_pvt::owner.

◆ my_set_outgoing()

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

Definition at line 2224 of file chan_dahdi.c.

2225{
2226 struct dahdi_pvt *p = pvt;
2227
2228 p->outgoing = is_outgoing;
2229}

References dahdi_pvt::outgoing.

◆ my_set_polarity()

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

Definition at line 2929 of file chan_dahdi.c.

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

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

2363{
2364 struct dahdi_pvt *p = pvt;
2365 p->pulsedial = flag;
2366}

References dahdi_pvt::pulsedial.

◆ my_set_ringtimeout()

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

Definition at line 2267 of file chan_dahdi.c.

2268{
2269 struct dahdi_pvt *p = pvt;
2270 p->ringt = ringt;
2271}

References dahdi_pvt::ringt.

◆ my_set_waitingfordt()

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

Definition at line 2273 of file chan_dahdi.c.

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

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

2976{
2977 struct dahdi_pvt *p = pvt;
2978 int x = DAHDI_START;
2979
2980 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2981}

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

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

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

2941{
2942 struct dahdi_pvt *p = pvt;
2943
2945 my_set_polarity(pvt, 0);
2946 }
2947}

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

1785{
1786 struct dahdi_pvt *p = pvt;
1787 p->callwaitingrepeat = 0;
1788 p->cidcwexpire = 0;
1789 p->cid_suppress_expire = 0;
1790
1791 return 0;
1792}

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

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

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

2514{
2515 struct dahdi_pvt *p = pvt;
2516 int da, db;
2517 int tchan;
2518 int tinthreeway;
2519
2522
2523 tchan = p->subs[da].chan;
2524 p->subs[da].chan = p->subs[db].chan;
2525 p->subs[db].chan = tchan;
2526
2527 tinthreeway = p->subs[da].inthreeway;
2528 p->subs[da].inthreeway = p->subs[db].inthreeway;
2529 p->subs[db].inthreeway = tinthreeway;
2530
2531 p->subs[da].owner = ast_a;
2532 p->subs[db].owner = ast_b;
2533
2534 if (ast_a)
2535 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
2536 if (ast_b)
2537 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
2538
2539 wakeup_sub(p, a);
2540 wakeup_sub(p, b);
2541
2542 return;
2543}
static void wakeup_sub(struct dahdi_pvt *p, int a)
static struct test_val b

References a, analogsub_to_dahdisub(), ast_channel_set_fd(), b, dahdi_subchannel::chan, 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 3003 of file chan_dahdi.c.

3004{
3005 struct dahdi_pvt *p = pvt;
3006
3007 dahdi_train_ec(p);
3008
3009 return 0;
3010}

References dahdi_train_ec().

◆ my_unallocate_sub()

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

Definition at line 2705 of file chan_dahdi.c.

2706{
2707 struct dahdi_pvt *p = pvt;
2708
2709 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
2710}

References analogsub_to_dahdisub(), and unalloc_sub().

◆ my_unlock_private()

static void my_unlock_private ( void *  pvt)
static

Definition at line 2031 of file chan_dahdi.c.

2032{
2033 struct dahdi_pvt *p = pvt;
2035}

References ast_mutex_unlock, and dahdi_pvt::lock.

◆ my_wait_event()

static int my_wait_event ( void *  pvt)
static

Definition at line 2837 of file chan_dahdi.c.

2838{
2839 struct dahdi_pvt *p = pvt;
2840
2841 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
2842}

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

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

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

3608{
3609 char s[sizeof(mwimonitornotify) + 164];
3610
3611 if (ast_strlen_zero(mailbox)) {
3612 return;
3613 }
3614
3615 ast_publish_mwi_state(mailbox, NULL, thereornot, thereornot);
3617 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
3618 ast_safe_system(s);
3619 }
3620}
static char mwimonitornotify[PATH_MAX]
Definition chan_dahdi.c:855
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(), 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 7266 of file chan_dahdi.c.

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

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

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

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

17056{
17057 struct dahdi_params dahdip;
17058 struct dahdi_pvt *pvt = ast_channel_tech_pvt(chan);
17059 if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
17060 ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", ast_channel_name(chan));
17061 return -1;
17062 }
17063 memset(&dahdip, 0, sizeof(dahdip));
17064 if (ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &dahdip)) {
17065 ast_log(LOG_WARNING, "Unable to get parameters of DAHDI channel %d: %s\n", pvt->subs[SUB_REAL].dfd, strerror(errno));
17066 return -1;
17067 }
17068 return dahdichan_read_property(ast_channel_tech_pvt(chan), &dahdip, "polarity", buffer, buflen);
17069}

References ast_channel_name(), 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 17071 of file chan_dahdi.c.

17072{
17073 struct dahdi_params dahdip;
17074 struct dahdi_pvt *pvt = ast_channel_tech_pvt(chan);
17075 if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
17076 ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", ast_channel_name(chan));
17077 return -1;
17078 }
17079 memset(&dahdip, 0, sizeof(dahdip));
17080 if (ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &dahdip)) {
17081 ast_log(LOG_WARNING, "Unable to get parameters of DAHDI channel %d: %s\n", pvt->subs[SUB_REAL].dfd, strerror(errno));
17082 return -1;
17083 }
17084 return dahdichan_write_property(ast_channel_tech_pvt(chan), &dahdip, "polarity", value);
17085}

References ast_channel_name(), 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 16893 of file chan_dahdi.c.

16894{
16895 if (!p->subs[subchan].owner) {
16896 return -1;
16897 }
16898 ast_channel_lock(p->subs[subchan].owner);
16899 snprintf(buffer, len, "%s", ast_channel_name(p->subs[subchan].owner));
16900 ast_channel_unlock(p->subs[subchan].owner);
16901 return 0;
16902}

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

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

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

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

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

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

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

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

9910{
9911 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
9912 RAII_VAR(struct ast_str *, dahdichan, ast_str_create(32), ast_free);
9913 if (!dahdichan) {
9914 return;
9915 }
9916
9917 ast_str_set(&dahdichan, 0, "%d", channel);
9918
9919 body = ast_json_pack("{s: s, s: s}",
9920 "DAHDIChannel", ast_str_buffer(dahdichan),
9921 "Status", status);
9922 if (!body) {
9923 return;
9924 }
9925
9927}
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 7758 of file chan_dahdi.c.

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

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

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

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

1418{
1419#ifdef HAVE_PRI
1420 struct doomed_pri *entry;
1421
1422 AST_LIST_LOCK(&doomed_pris);
1423 while ((entry = AST_LIST_REMOVE_HEAD(&doomed_pris, list))) {
1424 /* The span destruction must be done with this lock not held */
1425 AST_LIST_UNLOCK(&doomed_pris);
1426 ast_debug(4, "Destroying span %d from doomed queue.\n",
1427 entry->pri->span);
1428 pri_destroy_span(entry->pri);
1429 ast_free(entry);
1430 AST_LIST_LOCK(&doomed_pris);
1431 }
1432 AST_LIST_UNLOCK(&doomed_pris);
1433#endif
1434}
#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.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.

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

20745{
20746 int res = 0;
20747
20748 res = setup_dahdi(1);
20749 if (res) {
20750 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
20751 return -1;
20752 }
20753 return 0;
20754}

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

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

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

12269{
12270 /* If we're supposed to be stopped -- stay stopped */
12272 return 0;
12274 if (monitor_thread == pthread_self()) {
12276 ast_log(LOG_WARNING, "Cannot kill myself\n");
12277 return -1;
12278 }
12280 /* Wake up the thread */
12281 pthread_kill(monitor_thread, SIGURG);
12282 } else {
12283 /* Start a new monitor */
12286 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12287 return -1;
12288 }
12289 }
12291 return 0;
12292}
static void * do_monitor(void *data)

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

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

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

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

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

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

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

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

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

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

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

5205{
5206 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
5207}

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

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

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

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

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

5043{
5044 struct dahdi_hwgain hwgain;
5045
5046 hwgain.newgain = gain * 10.0;
5047 hwgain.tx = tx_direction;
5048 return ioctl(fd, DAHDI_SET_HWGAIN, &hwgain) < 0;
5049}

Referenced by dahdi_set_hwgain(), and mkintf().

◆ setup_dahdi()

static int setup_dahdi ( int  reload)
static

Definition at line 20484 of file chan_dahdi.c.

20485{
20486 int res;
20487 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
20488 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
20490
20491 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
20492 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
20493 } else {
20494 res = -1;
20495 }
20498 ast_cc_config_params_destroy(conf.chan.cc_params);
20499
20500 return res;
20501}

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

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

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

12575{
12576 return sigtype;
12577}
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 4372 of file chan_dahdi.c.

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

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

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

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

18527{
18528#if defined(HAVE_PRI) || defined(HAVE_SS7)
18529 int y;
18530#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18531#ifdef HAVE_PRI
18532 for (y = 0; y < NUM_SPANS; y++)
18533 ast_mutex_destroy(&pris[y].pri.lock);
18534#endif
18535#if defined(HAVE_SS7)
18536 for (y = 0; y < NUM_SPANS; y++)
18537 ast_mutex_destroy(&linksets[y].ss7.lock);
18538#endif /* defined(HAVE_SS7) */
18539 return __unload_module();
18540}

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

3795{
3797 if (p->subs[a].owner) {
3800 }
3801}
static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)

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 = ASTERISK_GPL_KEY , .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 20768 of file chan_dahdi.c.

◆ alarm

int alarm

Definition at line 4674 of file chan_dahdi.c.

Referenced by alarm2str().

◆ [struct]

struct { ... } alarms[]

Referenced by alarm2str().

◆ analog_callbacks

struct analog_callback analog_callbacks

Global analog callbacks to the upper layer.

Definition at line 3670 of file chan_dahdi.c.

3671{
3672 .play_tone = my_play_tone,
3673 .get_event = my_get_event,
3674 .wait_event = my_wait_event,
3675 .is_off_hook = my_is_off_hook,
3676 .set_echocanceller = my_set_echocanceller,
3677 .ring = my_ring,
3678 .flash = my_flash,
3679 .off_hook = my_off_hook,
3680 .dial_digits = my_dial_digits,
3681 .train_echocanceller = my_train_echocanceller,
3682 .on_hook = my_on_hook,
3683 .is_dialing = my_is_dialing,
3684 .allocate_sub = my_allocate_sub,
3685 .unallocate_sub = my_unallocate_sub,
3686 .swap_subs = my_swap_subchannels,
3687 .has_voicemail = my_has_voicemail,
3688 .check_for_conference = my_check_for_conference,
3689 .conf_add = my_conf_add,
3690 .conf_del = my_conf_del,
3691 .complete_conference_update = my_complete_conference_update,
3692 .start = my_start,
3693 .all_subchannels_hungup = my_all_subchannels_hungup,
3694 .lock_private = my_lock_private,
3695 .unlock_private = my_unlock_private,
3696 .deadlock_avoidance_private = my_deadlock_avoidance_private,
3697 .handle_dtmf = my_handle_dtmf,
3698 .wink = my_wink,
3699 .new_ast_channel = my_new_analog_ast_channel,
3700 .dsp_set_digitmode = my_dsp_set_digitmode,
3701 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
3702 .send_callerid = my_send_callerid,
3703 .callwait = my_callwait,
3704 .stop_callwait = my_stop_callwait,
3705 .get_callerid = my_get_callerid,
3706 .start_cid_detect = my_start_cid_detect,
3707 .stop_cid_detect = my_stop_cid_detect,
3708 .handle_notify_message = my_handle_notify_message,
3709 .increase_ss_count = my_increase_ss_count,
3710 .decrease_ss_count = my_decrease_ss_count,
3711 .distinctive_ring = my_distinctive_ring,
3712 .set_linear_mode = my_set_linear_mode,
3713 .set_inthreeway = my_set_inthreeway,
3714 .get_and_handle_alarms = my_get_and_handle_alarms,
3715 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
3716 .get_sub_fd = my_get_sub_fd,
3717 .set_cadence = my_set_cadence,
3718 .set_alarm = my_set_alarm,
3719 .set_dialing = my_set_dialing,
3720 .set_outgoing = my_set_outgoing,
3721 .set_ringtimeout = my_set_ringtimeout,
3722 .set_waitingfordt = my_set_waitingfordt,
3723 .check_waitingfordt = my_check_waitingfordt,
3724 .set_confirmanswer = my_set_confirmanswer,
3725 .check_confirmanswer = my_check_confirmanswer,
3726 .set_callwaiting = my_set_callwaiting,
3727 .cancel_cidspill = my_cancel_cidspill,
3728 .confmute = my_confmute,
3729 .set_pulsedial = my_set_pulsedial,
3730 .set_new_owner = my_set_new_owner,
3731 .get_orig_dialstring = my_get_orig_dialstring,
3732 .set_needringing = my_set_needringing,
3733 .set_polarity = my_set_polarity,
3734 .start_polarityswitch = my_start_polarityswitch,
3735 .answer_polarityswitch = my_answer_polarityswitch,
3736 .hangup_polarityswitch = my_hangup_polarityswitch,
3737 .have_progressdetect = my_have_progressdetect,
3738 .get_firstdigit_timeout = my_get_firstdigit_timeout,
3739 .get_matchdigit_timeout = my_get_matchdigit_timeout,
3740 .get_interdigit_timeout = my_get_interdigit_timeout,
3741};
static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
static void my_set_confirmanswer(void *pvt, int flag)
static int my_callwait(void *pvt)
static int my_check_confirmanswer(void *pvt)
static int my_is_dialing(void *pvt, enum analog_sub sub)
static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
static void my_cancel_cidspill(void *pvt)
static int my_set_echocanceller(void *pvt, int enable)
static void my_hangup_polarityswitch(void *pvt)
static int my_stop_cid_detect(void *pvt)
static int my_get_sub_fd(void *pvt, enum analog_sub sub)
static void my_set_needringing(void *pvt, int value)
static void my_unlock_private(void *pvt)
static void my_set_dialing(void *pvt, int is_dialing)
static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
static int my_on_hook(void *pvt)
static void my_set_pulsedial(void *pvt, int flag)
static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
static void my_set_alarm(void *pvt, int in_alarm)
static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
static int my_get_event(void *pvt)
static void my_set_callwaiting(void *pvt, int callwaiting_enable)
static int my_check_waitingfordt(void *pvt)
static void my_set_outgoing(void *pvt, int is_outgoing)
static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
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 void my_get_and_handle_alarms(void *pvt)
static void my_lock_private(void *pvt)
static int my_stop_callwait(void *pvt)
static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
static int my_confmute(void *pvt, int mute)
static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
static void my_decrease_ss_count(void)
static void my_start_polarityswitch(void *pvt)
static int my_wait_event(void *pvt)
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 int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
static int my_start(void *pvt)
static void my_answer_polarityswitch(void *pvt)
static int my_have_progressdetect(void *pvt)
static int my_train_echocanceller(void *pvt)
static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
static void my_all_subchannels_hungup(void *pvt)
static int my_ring(void *pvt)
static int my_start_cid_detect(void *pvt, int cid_signalling)
static int my_complete_conference_update(void *pvt, int needconference)
static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
static void my_increase_ss_count(void)
static int my_wink(void *pvt, enum analog_sub sub)
static int my_conf_add(void *pvt, enum analog_sub sub)
static int my_dsp_reset_and_flush_digits(void *pvt)
static int my_has_voicemail(void *pvt)
static const char * my_get_orig_dialstring(void *pvt)
static int my_conf_del(void *pvt, enum analog_sub sub)
static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
static void * my_get_sigpvt_bridged_channel(struct ast_channel *chan)
static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
static int my_check_for_conference(void *pvt)
static int my_flash(void *pvt)
static void my_deadlock_avoidance_private(void *pvt)
static void my_set_ringtimeout(void *pvt, int ringt)

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

843{{250, 10000}};

Referenced by mwi_send_process_buffer().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 20768 of file chan_dahdi.c.

◆ cadences

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
static

Definition at line 824 of file chan_dahdi.c.

824 {
825 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
826 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
827 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
828 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
829};

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

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

835 {
836 2, /*!< Right after first long ring */
837 4, /*!< Right after long part */
838 3, /*!< After third chirp */
839 2, /*!< Second spell */
840};

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

◆ config

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

Definition at line 803 of file chan_dahdi.c.

Referenced by setup_dahdi_int().

◆ dahdi_cli

struct ast_cli_entry dahdi_cli[]
static

Definition at line 16824 of file chan_dahdi.c.

16824 {
16826 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
16827 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
16828 AST_CLI_DEFINE(dahdi_destroy_channels, "Destroy channels"),
16829 AST_CLI_DEFINE(dahdi_create_channels, "Create channels"),
16830 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16831 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16832 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16833 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16834 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16835 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16836 AST_CLI_DEFINE(dahdi_set_mwi, "Sets/unsets MWI (Message Waiting Indicator) manually on a channel"),
16837};
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_destroy_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_dahdi_show_cadences(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 char * dahdi_create_channels(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_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197

Referenced by __unload_module(), and load_module().

◆ dahdi_tech

struct ast_channel_tech dahdi_tech
static

Definition at line 1291 of file chan_dahdi.c.

1291 {
1292 .type = "DAHDI",
1293 .description = tdesc,
1294 .requester = dahdi_request,
1295 .send_digit_begin = dahdi_digit_begin,
1296 .send_digit_end = dahdi_digit_end,
1297 .send_text = dahdi_sendtext,
1298 .call = dahdi_call,
1299 .hangup = dahdi_hangup,
1300 .answer = dahdi_answer,
1301 .read = dahdi_read,
1302 .write = dahdi_write,
1303 .exception = dahdi_exception,
1304 .indicate = dahdi_indicate,
1305 .fixup = dahdi_fixup,
1306 .setoption = dahdi_setoption,
1307 .queryoption = dahdi_queryoption,
1308 .func_channel_read = dahdi_func_read,
1309 .func_channel_write = dahdi_func_write,
1310 .devicestate = dahdi_devicestate,
1311 .cc_callback = dahdi_cc_callback,
1312};
static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
Callback made when dial failed to get a channel out of dahdi_request().
static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
static int dahdi_digit_begin(struct ast_channel *ast, char digit)
static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
static int dahdi_devicestate(const char *data)
static int dahdi_hangup(struct ast_channel *ast)
static int dahdi_sendtext(struct ast_channel *c, const char *text)
static int dahdi_answer(struct ast_channel *ast)
static const char tdesc[]
Definition chan_dahdi.c:782
static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
static struct ast_frame * dahdi_exception(struct ast_channel *ast)
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 int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
static struct ast_frame * dahdi_read(struct ast_channel *ast)

Referenced by __unload_module(), analog_ss_thread(), dahdi_new(), load_module(), and my_get_sigpvt_bridged_channel().

◆ 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)
static int dahdichan_read(struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)

Definition at line 17047 of file chan_dahdi.c.

17047 {
17048 .name = "DAHDI_CHANNEL",
17049 .write = dahdichan_write,
17050 .read = dahdichan_read,
17051};

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.

749{
750 .flags = 0,
751 .max_size = 200,
752 .resync_threshold = 1000,
753 .impl = "fixed",
754 .target_extra = 40,
755};

Referenced by setup_dahdi_int().

◆ defaultcic

char defaultcic[64] = ""
static

Definition at line 851 of file chan_dahdi.c.

Referenced by process_dahdi().

◆ defaultozz

char defaultozz[64] = ""
static

Definition at line 852 of file chan_dahdi.c.

Referenced by process_dahdi().

◆ distinctiveringaftercid

int distinctiveringaftercid = 0
static

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

Referenced by do_monitor(), and process_dahdi().

◆ events

const char* const events[]
static

Definition at line 4651 of file chan_dahdi.c.

4651 {
4652 "No event",
4653 "On hook",
4654 "Ring/Answered",
4655 "Wink/Flash",
4656 "Alarm",
4657 "No more alarm",
4658 "HDLC Abort",
4659 "HDLC Overrun",
4660 "HDLC Bad FCS",
4661 "Dial Complete",
4662 "Ringer On",
4663 "Ringer Off",
4664 "Hook Transition Complete",
4665 "Bits Changed",
4666 "Pulse Start",
4667 "Timer Expired",
4668 "Timer Ping",
4669 "Polarity Reversal",
4670 "Ring Begin",
4671};

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

Referenced by build_channels(), and process_dahdi().

◆ ifcount

int ifcount = 0
static

Definition at line 883 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 1057 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

◆ lbostr

const char* const lbostr[]
static

Definition at line 735 of file chan_dahdi.c.

735 {
736"0 db (CSU)/0-133 feet (DSX-1)",
737"133-266 feet (DSX-1)",
738"266-399 feet (DSX-1)",
739"399-533 feet (DSX-1)",
740"533-655 feet (DSX-1)",
741"-7.5db (CSU)",
742"-15db (CSU)",
743"-22.5db (CSU)"
744};

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

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

◆ monlock

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

Definition at line 891 of file chan_dahdi.c.

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

◆ mwilevel

int mwilevel = 512
static

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

Referenced by mwi_send_init(), and process_dahdi().

◆ name

char* name

Definition at line 4675 of file chan_dahdi.c.

Referenced by __dahdi_exception(), analog_ss_thread(), mwi_thread(), and my_get_callerid().

◆ num_cadence

int num_cadence = 4
static

Definition at line 819 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 865 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)
static int polarity_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)

Definition at line 17087 of file chan_dahdi.c.

17087 {
17088 .name = "POLARITY",
17089 .write = polarity_write,
17090 .read = polarity_read,
17091};

Referenced by __unload_module(), and load_module().

◆ progzone

char progzone[10] = ""
static

Definition at line 860 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

◆ report_alarms

int report_alarms = REPORT_CHANNEL_ALARMS
static

Definition at line 872 of file chan_dahdi.c.

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

◆ restart_lock

ast_mutex_t restart_lock = AST_MUTEX_INIT_VALUE
static

Definition at line 898 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 945 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 3744 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 = AST_MUTEX_INIT_VALUE
static

◆ subnames

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

Definition at line 1050 of file chan_dahdi.c.

1050 {
1051 "Real",
1052 "Callwait",
1053 "Threeway"
1054};

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

◆ tdesc

const char tdesc[] = "DAHDI Telephony"
static

Definition at line 782 of file chan_dahdi.c.

◆ usedistinctiveringdetection

int usedistinctiveringdetection = 0
static

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

Referenced by process_dahdi().