Asterisk - The Open Source Telephony Project GIT-master-8924258
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
Data Structures | Macros | Functions | Variables
chan_dahdi.c File Reference

DAHDI for Pseudo TDM. More...

#include "asterisk.h"
#include <sys/sysmacros.h>
#include <signal.h>
#include <sys/stat.h>
#include <math.h>
#include "sig_analog.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/file.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/callerid.h"
#include "asterisk/adsi.h"
#include "asterisk/cli.h"
#include "asterisk/pickup.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/say.h"
#include "asterisk/tdd.h"
#include "asterisk/mwi.h"
#include "asterisk/dsp.h"
#include "asterisk/astdb.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"
#include "asterisk/term.h"
#include "asterisk/utils.h"
#include "asterisk/transcap.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/smdi.h"
#include "asterisk/devicestate.h"
#include "asterisk/paths.h"
#include "asterisk/ccss.h"
#include "asterisk/features_config.h"
#include "asterisk/bridge.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/parking.h"
#include "asterisk/format_cache.h"
#include "chan_dahdi.h"
#include "dahdi/bridge_native_dahdi.h"
Include dependency graph for chan_dahdi.c:

Go to the source code of this file.

Data Structures

struct  dahdi_chan_conf
 Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section of chan_dahdi.conf. Generally there is a field here for every possible configuration item. More...
 
struct  dahdi_starting_point
 
struct  mwi_thread_data
 

Macros

#define ASCII_BYTES_PER_CHAR   80
 
#define AST_LAW(p)   (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw)
 
#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
 
#define CALLPROGRESS_FAX_INCOMING   4
 
#define CALLPROGRESS_FAX_OUTGOING   2
 
#define CALLPROGRESS_PROGRESS   1
 
#define CALLWAITING_REPEAT_SAMPLES   ((10000 * 8) / READ_SIZE)
 
#define CALLWAITING_SILENT_SAMPLES   ((300 * 8) / READ_SIZE)
 
#define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE)
 
#define CANBUSYDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
 
#define CANPROGRESSDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
 
#define CHAN_PSEUDO   -2
 
#define CIDCW_EXPIRE_SAMPLES   ((500 * 8) / READ_SIZE)
 
#define DEFAULT_CIDRINGS   1
 Typically, how many rings before we should send Caller*ID. More...
 
#define DEFAULT_DIALTONE_DETECT_TIMEOUT   ((10000 * 8) / READ_SIZE)
 
#define DEFAULT_RINGT   ((8000 * 8) / READ_SIZE)
 
#define END_SILENCE_LEN   400
 
#define FORMAT   "%7s %4d %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"
 
#define FORMAT   "%4d %-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
 
#define FORMAT2   "%7s %4s %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"
 
#define FORMAT2   "%4s %-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
 
#define gen_pvt_field_callback(type, field)
 
#define GET_CHANNEL(p)   ((p)->channel)
 
#define HANGUP   1
 
#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)
 
#define HEADER_MS   50
 
#define ISTRUNK(p)
 
#define MASK_AVAIL   (1 << 0)
 
#define MASK_INUSE   (1 << 1)
 
#define MAX_CHANLIST_LEN   80
 
#define MIN_MS_SINCE_FLASH   ((2000) )
 
#define NEED_MFDETECT(p)   (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
 Signaling types that need to use MF detection should be placed in this macro. More...
 
#define NUM_CADENCE_MAX   25
 
#define NUM_SPANS   32
 
#define POLARITY_IDLE   0
 
#define POLARITY_REV   1
 
#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)
 
#define PROC_DAHDI_OPT_NOWARN   (1 << 1)
 
#define READ_SIZE   160
 
#define REPORT_CHANNEL_ALARMS   1
 
#define REPORT_SPAN_ALARMS   2
 
#define sig2str   dahdi_sig2str
 
#define SMDI_MD_WAIT_TIMEOUT   1500 /* 1.5 seconds */
 
#define TRAILER_MS   5
 
#define TRANSFER   0
 

Functions

static struct ast_frame__dahdi_exception (struct ast_channel *ast)
 
static void __reg_module (void)
 
static int __unload_module (void)
 
static void __unreg_module (void)
 
int _dahdi_get_index (struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
 
static int action_dahdidialoffhook (struct mansession *s, const struct message *m)
 
static int action_dahdidndoff (struct mansession *s, const struct message *m)
 
static int action_dahdidndon (struct mansession *s, const struct message *m)
 
static int action_dahdirestart (struct mansession *s, const struct message *m)
 
static int action_dahdishowchannels (struct mansession *s, const struct message *m)
 
static int action_dahdishowstatus (struct mansession *s, const struct message *m)
 
static int action_transfer (struct mansession *s, const struct message *m)
 
static int action_transferhangup (struct mansession *s, const struct message *m)
 
static char * alarm2str (int alm)
 
static int alloc_sub (struct dahdi_pvt *p, int x)
 
static void * analog_ss_thread (void *data)
 
static int analog_tone_to_dahditone (enum analog_tone tone)
 
static int analogsub_to_dahdisub (enum analog_sub analogsub)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int attempt_transfer (struct dahdi_pvt *p)
 
static int available (struct dahdi_pvt **pvt, int is_specific_channel)
 
static void build_alarm_info (char *restrict alarmstr, struct dahdi_spaninfo *spaninfo)
 
static int build_channels (struct dahdi_chan_conf *conf, const char *value, int reload, int lineno)
 
static int bump_gains (struct dahdi_pvt *p)
 
static int calc_energy (const unsigned char *buf, int len, struct ast_format *law)
 
static int canmatch_featurecode (const char *pickupexten, const char *exten)
 
static int check_for_conference (struct dahdi_pvt *p)
 
static int conf_add (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
 
static int conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
 
static struct ast_strcreate_channel_name (struct dahdi_pvt *i)
 
static void dahdi_ami_channel_event (struct dahdi_pvt *p, struct ast_channel *chan)
 
static int dahdi_answer (struct ast_channel *ast)
 
static int dahdi_call (struct ast_channel *ast, const char *rdest, int timeout)
 
static int dahdi_callwait (struct ast_channel *ast)
 
static int dahdi_cc_callback (struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
 Callback made when dial failed to get a channel out of dahdi_request(). More...
 
static struct dahdi_chan_conf dahdi_chan_conf_default (void)
 
static void dahdi_close (int fd)
 
static void dahdi_close_sub (struct dahdi_pvt *chan_pvt, int sub_num)
 
void dahdi_conf_update (struct dahdi_pvt *p)
 
static int dahdi_confmute (struct dahdi_pvt *p, int muted)
 
static int dahdi_create_channel_range (int start, int end)
 
static char * dahdi_create_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void dahdi_destroy_channel_range (int start, int end)
 
static char * dahdi_destroy_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int dahdi_devicestate (const char *data)
 
static int dahdi_dial_str (struct dahdi_pvt *pvt, int operation, const char *dial_str)
 
static int dahdi_digit_begin (struct ast_channel *ast, char digit)
 
static int dahdi_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
 
static int dahdi_dnd (struct dahdi_pvt *dahdichan, int flag)
 enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel More...
 
void dahdi_dtmf_detect_disable (struct dahdi_pvt *p)
 
void dahdi_dtmf_detect_enable (struct dahdi_pvt *p)
 
void dahdi_ec_disable (struct dahdi_pvt *p)
 
void dahdi_ec_enable (struct dahdi_pvt *p)
 
static struct ast_framedahdi_exception (struct ast_channel *ast)
 
static int dahdi_fake_event (struct dahdi_pvt *p, int mode)
 
static int dahdi_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
 
static int dahdi_func_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
 
static int dahdi_func_write (struct ast_channel *chan, const char *function, char *data, const char *value)
 
static int dahdi_get_event (int fd)
 Avoid the silly dahdi_getevent which ignores a bunch of events. More...
 
static void dahdi_handle_dtmf (struct ast_channel *ast, int idx, struct ast_frame **dest)
 
static struct ast_framedahdi_handle_event (struct ast_channel *ast)
 
static int dahdi_hangup (struct ast_channel *ast)
 
static void dahdi_iflist_extract (struct dahdi_pvt *pvt)
 
static void dahdi_iflist_insert (struct dahdi_pvt *pvt)
 
static int dahdi_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen)
 
static void dahdi_lock_sub_owner (struct dahdi_pvt *pvt, int sub_idx)
 
void dahdi_master_slave_link (struct dahdi_pvt *slave, struct dahdi_pvt *master)
 
void dahdi_master_slave_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
 
static struct ast_channeldahdi_new (struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid)
 
static struct ast_channeldahdi_new_callid_clean (struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid, int callid_created)
 
static int dahdi_open (char *fn)
 
static int dahdi_queryoption (struct ast_channel *chan, int option, void *data, int *datalen)
 
static void dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f)
 
static struct ast_framedahdi_read (struct ast_channel *ast)
 
static struct ast_channeldahdi_request (const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
 
static int dahdi_restart (void)
 
static char * dahdi_restart_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int dahdi_ring_phone (struct dahdi_pvt *p)
 
static int dahdi_sendtext (struct ast_channel *c, const char *text)
 
static char * dahdi_set_dnd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int dahdi_set_hook (int fd, int hs)
 
static char * dahdi_set_hwgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dahdi_set_mwi (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dahdi_set_swgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int dahdi_setlinear (int dfd, int linear)
 
static int dahdi_setoption (struct ast_channel *chan, int option, void *data, int datalen)
 
static char * dahdi_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dahdi_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dahdi_show_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dahdi_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dahdi_sig2str (int sig)
 
static void dahdi_softhangup_all (void)
 
static void dahdi_train_ec (struct dahdi_pvt *p)
 
static int dahdi_wait_event (int fd)
 Avoid the silly dahdi_waitevent which ignores a bunch of events. More...
 
static int dahdi_wink (struct dahdi_pvt *p, int index)
 
static int dahdi_write (struct ast_channel *ast, struct ast_frame *frame)
 
static struct ast_manager_event_blobdahdichannel_to_ami (struct stasis_message *msg)
 
static enum analog_event dahdievent_to_analogevent (int event)
 
static enum analog_sigtype dahdisig_to_analogsig (int sig)
 
static void deep_copy_dahdi_chan_conf (struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
 
static void destroy_all_channels (void)
 
static void destroy_channel (struct dahdi_pvt *cur, int now)
 
static void destroy_dahdi_pvt (struct dahdi_pvt *pvt)
 
static struct dahdi_pvtdetermine_starting_point (const char *data, struct dahdi_starting_point *param)
 
static int digit_to_dtmfindex (char digit)
 
static void * do_monitor (void *data)
 
static int drc_sample (int sample, float drc)
 
static struct dahdi_pvtduplicate_pseudo (struct dahdi_pvt *src)
 
static const char * event2str (int event)
 
static void fill_rxgain (struct dahdi_gains *g, float gain, float drc, int law)
 
static void fill_txgain (struct dahdi_gains *g, float gain, float drc, int law)
 
static struct dahdi_pvtfind_channel (int channel)
 
static struct dahdi_pvtfind_channel_from_str (const char *channel)
 
static struct dahdi_pvtfind_next_iface_in_span (struct dahdi_pvt *cur)
 
static struct dahdi_pvtfxo_pvt (struct ast_channel *chan)
 Return DAHDI pivot if channel is FXO signalled. More...
 
 gen_pvt_field_callback (int, firstdigit_timeout)
 
 gen_pvt_field_callback (int, interdigit_timeout)
 
 gen_pvt_field_callback (int, matchdigit_timeout)
 
static int get_alarms (struct dahdi_pvt *p)
 
static void handle_alarms (struct dahdi_pvt *p, int alms)
 
static void handle_clear_alarms (struct dahdi_pvt *p)
 
static char * handle_dahdi_show_cadences (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static struct dahdi_pvthandle_init_event (struct dahdi_pvt *i, int event)
 
static int has_voicemail (struct dahdi_pvt *p)
 
static int is_group_or_channel_match (struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
 
static int isourconf (struct dahdi_pvt *p, struct dahdi_subchannel *c)
 
static int isslavenative (struct dahdi_pvt *p, struct dahdi_pvt **out)
 
static int load_module (void)
 Load the module. More...
 
static struct dahdi_pvtmkintf (int channel, const struct dahdi_chan_conf *conf, int reloading)
 
static void monitor_pfds_clean (void *arg)
 
static int mwi_send_init (struct dahdi_pvt *pvt)
 
static int mwi_send_process_buffer (struct dahdi_pvt *pvt, int num_read)
 
static int mwi_send_process_event (struct dahdi_pvt *pvt, int event)
 
static void * mwi_thread (void *data)
 
static void my_all_subchannels_hungup (void *pvt)
 
static int my_allocate_sub (void *pvt, enum analog_sub analogsub)
 
static void my_answer_polarityswitch (void *pvt)
 
static int my_callwait (void *pvt)
 
static void my_cancel_cidspill (void *pvt)
 
static int my_check_confirmanswer (void *pvt)
 
static int my_check_for_conference (void *pvt)
 
static int my_check_waitingfordt (void *pvt)
 
static int my_complete_conference_update (void *pvt, int needconference)
 
static int my_conf_add (void *pvt, enum analog_sub sub)
 
static int my_conf_del (void *pvt, enum analog_sub sub)
 
static int my_confmute (void *pvt, int mute)
 
static int my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
 
static void my_deadlock_avoidance_private (void *pvt)
 
static void my_decrease_ss_count (void)
 
static int my_dial_digits (void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
 
static int my_distinctive_ring (struct ast_channel *chan, void *pvt, int idx, int *ringdata)
 
static int my_dsp_reset_and_flush_digits (void *pvt)
 
static int my_dsp_set_digitmode (void *pvt, enum analog_dsp_digitmode mode)
 
static int my_flash (void *pvt)
 
static void my_get_and_handle_alarms (void *pvt)
 
static int my_get_callerid (void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
 
static int my_get_event (void *pvt)
 
static const char * my_get_orig_dialstring (void *pvt)
 
static void * my_get_sigpvt_bridged_channel (struct ast_channel *chan)
 
static int my_get_sub_fd (void *pvt, enum analog_sub sub)
 
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
 
static void my_handle_dtmf (void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
 
static void my_handle_notify_message (struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
 
static void my_hangup_polarityswitch (void *pvt)
 
static int my_has_voicemail (void *pvt)
 
static int my_have_progressdetect (void *pvt)
 
static void my_increase_ss_count (void)
 
static int my_is_dialing (void *pvt, enum analog_sub sub)
 
static int my_is_off_hook (void *pvt)
 
static void my_lock_private (void *pvt)
 
static struct ast_channelmy_new_analog_ast_channel (void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
 
static int my_off_hook (void *pvt)
 
static int my_on_hook (void *pvt)
 
static int my_play_tone (void *pvt, enum analog_sub sub, enum analog_tone tone)
 
static int my_ring (void *pvt)
 
static int my_send_callerid (void *pvt, int cwcid, struct ast_party_caller *caller)
 
static void my_set_alarm (void *pvt, int in_alarm)
 
static void my_set_cadence (void *pvt, int *cid_rings, struct ast_channel *ast)
 
static void my_set_callwaiting (void *pvt, int callwaiting_enable)
 
static void my_set_confirmanswer (void *pvt, int flag)
 
static void my_set_dialing (void *pvt, int is_dialing)
 
static int my_set_echocanceller (void *pvt, int enable)
 
static void my_set_inthreeway (void *pvt, enum analog_sub sub, int inthreeway)
 
static int my_set_linear_mode (void *pvt, enum analog_sub sub, int linear_mode)
 
static void my_set_needringing (void *pvt, int value)
 
static void my_set_new_owner (void *pvt, struct ast_channel *new_owner)
 
static void my_set_outgoing (void *pvt, int is_outgoing)
 
static void my_set_polarity (void *pvt, int value)
 
static void my_set_pulsedial (void *pvt, int flag)
 
static void my_set_ringtimeout (void *pvt, int ringt)
 
static void my_set_waitingfordt (void *pvt, struct ast_channel *ast)
 
static int my_start (void *pvt)
 
static int my_start_cid_detect (void *pvt, int cid_signalling)
 
static void my_start_polarityswitch (void *pvt)
 
static int my_stop_callwait (void *pvt)
 
static int my_stop_cid_detect (void *pvt)
 
static void my_swap_subchannels (void *pvt, enum analog_sub a, struct ast_channel *ast_a, enum analog_sub b, struct ast_channel *ast_b)
 
static int my_train_echocanceller (void *pvt)
 
static int my_unallocate_sub (void *pvt, enum analog_sub analogsub)
 
static void my_unlock_private (void *pvt)
 
static int my_wait_event (void *pvt)
 
static int my_wink (void *pvt, enum analog_sub sub)
 
static void notify_message (char *mailbox, int thereornot)
 Send MWI state change. More...
 
static int parse_buffers_policy (const char *parse, int *num_buffers, int *policy)
 
static void parse_busy_pattern (struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
 
static int polarity_read (struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)
 
static int polarity_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 
static int process_dahdi (struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
 
static void process_echocancel (struct dahdi_chan_conf *confp, const char *data, unsigned int line)
 
static void publish_channel_alarm (int channel, const char *alarm_txt)
 
static void publish_channel_alarm_clear (int channel)
 
static void publish_dahdichannel (struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
 Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages. More...
 
static void publish_dnd_state (int channel, const char *status)
 
static void publish_span_alarm (int span, const char *alarm_txt)
 
static void publish_span_alarm_clear (int span)
 
static void release_doomed_pris (void)
 
static int reload (void)
 
static int reset_conf (struct dahdi_pvt *p)
 
static int restart_monitor (void)
 
static int restore_conference (struct dahdi_pvt *p)
 
static int restore_gains (struct dahdi_pvt *p)
 
static int revert_fax_buffers (struct dahdi_pvt *p, struct ast_channel *ast)
 
static int save_conference (struct dahdi_pvt *p)
 
static int send_callerid (struct dahdi_pvt *p)
 
static int send_cwcidspill (struct dahdi_pvt *p)
 
static int set_actual_gain (int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
 
static int set_actual_rxgain (int fd, float gain, float drc, int law)
 
static int set_actual_txgain (int fd, float gain, float drc, int law)
 
static int set_hwgain (int fd, float gain, int tx_direction)
 
static int setup_dahdi (int reload)
 
static int setup_dahdi_int (int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
 
static int sigtype_to_signalling (int sigtype)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (dahdichannel_type,.to_ami=dahdichannel_to_ami,)
 
static void swap_subs (struct dahdi_pvt *p, int a, int b)
 
static int unalloc_sub (struct dahdi_pvt *p, int x)
 
static int unload_module (void)
 
static void wakeup_sub (struct dahdi_pvt *p, int a)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = tdesc , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .requires = "ccss", .optional_modules = "res_smdi", }
 
struct {
   int   alarm
 
   char *   name
 
alarms []
 
struct analog_callback analog_callbacks
 
static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
 
static int cidrings [NUM_CADENCE_MAX]
 cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on. More...
 
static const char config [] = "chan_dahdi.conf"
 
static struct ast_cli_entry dahdi_cli []
 
static struct ast_channel_tech dahdi_tech
 
static struct ast_jb_conf default_jbconf
 
static char defaultcic [64] = ""
 
static char defaultozz [64] = ""
 
static int distinctiveringaftercid = 0
 
static int dtmfcid_level = 256
 
static const char *const events []
 
static struct ast_jb_conf global_jbconf
 
static int has_pseudo
 
static int ifcount = 0
 
static struct dahdi_pvtifend = NULL
 
static struct dahdi_pvtiflist = NULL
 
static ast_mutex_t iflock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Protect the interface list (of dahdi_pvt's) More...
 
static const char *const lbostr []
 
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use. More...
 
static ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. More...
 
static int mwilevel = 512
 
static char mwimonitornotify [PATH_MAX] = ""
 
static int mwisend_rpas = 0
 
static int num_cadence = 4
 
static int num_restart_pending = 0
 
static int numbufs = 4
 
static struct ast_custom_function polarity_function
 
static char progzone [10] = ""
 
static int report_alarms = REPORT_CHANNEL_ALARMS
 
static ast_mutex_t restart_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base. More...
 
static struct dahdi_pvtround_robin [64]
 
static ast_cond_t ss_thread_complete
 
static int ss_thread_count = 0
 
static ast_mutex_t ss_thread_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
const char *const subnames []
 
static const char tdesc [] = "DAHDI Telephony"
 
static int usedistinctiveringdetection = 0
 
static int user_has_defined_cadences = 0
 

Detailed Description

DAHDI for Pseudo TDM.

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

Connects to the DAHDI telephony library as well as libpri. Libpri is optional and needed only if you are going to use ISDN connections.

You need to install libraries before you attempt to compile and install the DAHDI channel.

Todo:
Deprecate the "musiconhold" configuration option post 1.4

Definition in file chan_dahdi.c.

Macro Definition Documentation

◆ ASCII_BYTES_PER_CHAR

#define ASCII_BYTES_PER_CHAR   80

◆ AST_LAW

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

Definition at line 712 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX

#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)

Definition at line 752 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX_INCOMING

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 751 of file chan_dahdi.c.

◆ CALLPROGRESS_FAX_OUTGOING

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 750 of file chan_dahdi.c.

◆ CALLPROGRESS_PROGRESS

#define CALLPROGRESS_PROGRESS   1

Definition at line 749 of file chan_dahdi.c.

◆ CALLWAITING_REPEAT_SAMPLES

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

10,000 ms

Definition at line 870 of file chan_dahdi.c.

◆ CALLWAITING_SILENT_SAMPLES

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

300 ms

Definition at line 869 of file chan_dahdi.c.

◆ CALLWAITING_SUPPRESS_SAMPLES

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

100 ms

Definition at line 871 of file chan_dahdi.c.

◆ CANBUSYDETECT

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

Definition at line 784 of file chan_dahdi.c.

◆ CANPROGRESSDETECT

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

Definition at line 785 of file chan_dahdi.c.

◆ CHAN_PSEUDO

#define CHAN_PSEUDO   -2

Definition at line 747 of file chan_dahdi.c.

◆ CIDCW_EXPIRE_SAMPLES

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

500 ms

Definition at line 872 of file chan_dahdi.c.

◆ DEFAULT_CIDRINGS

#define DEFAULT_CIDRINGS   1

Typically, how many rings before we should send Caller*ID.

Note
Define ZHONE_HACK to cause us to go off hook and then back on hook when the user hangs up to reset the state machine so ring works properly. This is used to be able to support kewlstart by putting the zhone in groundstart mode since their forward disconnect supervision is entirely broken even though their documentation says it isn't and their support is entirely unwilling to provide any assistance with their channel banks even though their web site says they support their products for life.

Definition at line 710 of file chan_dahdi.c.

◆ DEFAULT_DIALTONE_DETECT_TIMEOUT

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

10,000 ms

Definition at line 875 of file chan_dahdi.c.

◆ DEFAULT_RINGT

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

8,000 ms

Definition at line 874 of file chan_dahdi.c.

◆ END_SILENCE_LEN

#define END_SILENCE_LEN   400

◆ FORMAT [1/2]

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

◆ FORMAT [2/2]

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

◆ FORMAT2 [1/2]

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

◆ FORMAT2 [2/2]

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

◆ gen_pvt_field_callback

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

Definition at line 3673 of file chan_dahdi.c.

◆ GET_CHANNEL

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

Definition at line 1250 of file chan_dahdi.c.

◆ HANGUP

#define HANGUP   1

Definition at line 16817 of file chan_dahdi.c.

◆ HEADER_LEN

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

◆ HEADER_MS

#define HEADER_MS   50

◆ ISTRUNK

#define ISTRUNK (   p)
Value:
((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
(p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
#define SIG_FXSLS
Definition: chan_dahdi.h:788
#define SIG_FXSKS
Definition: chan_dahdi.h:790
#define SIG_FXSGS
Definition: chan_dahdi.h:789
#define SIG_PRI
Definition: chan_dahdi.h:802

Definition at line 781 of file chan_dahdi.c.

◆ MASK_AVAIL

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 866 of file chan_dahdi.c.

◆ MASK_INUSE

#define MASK_INUSE   (1 << 1)

Channel currently in use

Definition at line 867 of file chan_dahdi.c.

◆ MAX_CHANLIST_LEN

#define MAX_CHANLIST_LEN   80

The length of the parameters list of 'dahdichan'.

Todo:
Move definition of MAX_CHANLIST_LEN to a proper place.

Definition at line 18377 of file chan_dahdi.c.

◆ MIN_MS_SINCE_FLASH

#define MIN_MS_SINCE_FLASH   ((2000) )

2000 ms

Definition at line 873 of file chan_dahdi.c.

◆ NEED_MFDETECT

#define NEED_MFDETECT (   p)    (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))

Signaling types that need to use MF detection should be placed in this macro.

Definition at line 716 of file chan_dahdi.c.

◆ NUM_CADENCE_MAX

#define NUM_CADENCE_MAX   25

Definition at line 754 of file chan_dahdi.c.

◆ NUM_SPANS

#define NUM_SPANS   32

Definition at line 744 of file chan_dahdi.c.

◆ POLARITY_IDLE

#define POLARITY_IDLE   0

Definition at line 983 of file chan_dahdi.c.

◆ POLARITY_REV

#define POLARITY_REV   1

Definition at line 984 of file chan_dahdi.c.

◆ PROC_DAHDI_OPT_NOCHAN

#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)

process_dahdi() - ignore keyword 'channel' and similar

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

◆ READ_SIZE

#define READ_SIZE   160

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

Definition at line 864 of file chan_dahdi.c.

◆ REPORT_CHANNEL_ALARMS

#define REPORT_CHANNEL_ALARMS   1

Definition at line 806 of file chan_dahdi.c.

◆ REPORT_SPAN_ALARMS

#define REPORT_SPAN_ALARMS   2

Definition at line 807 of file chan_dahdi.c.

◆ sig2str

#define sig2str   dahdi_sig2str

Definition at line 4785 of file chan_dahdi.c.

◆ SMDI_MD_WAIT_TIMEOUT

#define SMDI_MD_WAIT_TIMEOUT   1500 /* 1.5 seconds */

Definition at line 673 of file chan_dahdi.c.

◆ TRAILER_MS

#define TRAILER_MS   5

◆ TRANSFER

#define TRANSFER   0

Definition at line 16816 of file chan_dahdi.c.

Function Documentation

◆ __dahdi_exception()

static struct ast_frame * __dahdi_exception ( struct ast_channel ast)
static

Definition at line 8721 of file chan_dahdi.c.

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

◆ __unload_module()

static int __unload_module ( void  )
static

Definition at line 18188 of file chan_dahdi.c.

18189{
18190 struct dahdi_pvt *p;
18191#if defined(HAVE_PRI) || defined(HAVE_SS7)
18192 int i, j;
18193#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18194
18195#ifdef HAVE_PRI
18196 for (i = 0; i < NUM_SPANS; i++) {
18197 if (pris[i].pri.master != AST_PTHREADT_NULL) {
18198 pthread_cancel(pris[i].pri.master);
18199 pthread_kill(pris[i].pri.master, SIGURG);
18200 }
18201 }
18202 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18203 ast_unregister_application(dahdi_send_keypad_facility_app);
18204#ifdef HAVE_PRI_PROG_W_CAUSE
18205 ast_unregister_application(dahdi_send_callrerouting_facility_app);
18206#endif
18207#endif
18208#if defined(HAVE_SS7)
18209 for (i = 0; i < NUM_SPANS; i++) {
18210 if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
18211 pthread_cancel(linksets[i].ss7.master);
18212 pthread_kill(linksets[i].ss7.master, SIGURG);
18213 }
18214 }
18215 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18216#endif /* defined(HAVE_SS7) */
18217#if defined(HAVE_OPENR2)
18218 dahdi_r2_destroy_links();
18219 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18220 ast_unregister_application(dahdi_accept_r2_call_app);
18221#endif
18222
18224
18226 ast_manager_unregister("DAHDIDialOffhook");
18227 ast_manager_unregister("DAHDIHangup");
18228 ast_manager_unregister("DAHDITransfer");
18229 ast_manager_unregister("DAHDIDNDoff");
18230 ast_manager_unregister("DAHDIDNDon");
18231 ast_manager_unregister("DAHDIShowChannels");
18232 ast_manager_unregister("DAHDIShowStatus");
18233 ast_manager_unregister("DAHDIRestart");
18234#if defined(HAVE_PRI)
18235 ast_manager_unregister("PRIShowSpans");
18236 ast_manager_unregister("PRIDebugSet");
18237 ast_manager_unregister("PRIDebugFileSet");
18238 ast_manager_unregister("PRIDebugFileUnset");
18239#endif /* defined(HAVE_PRI) */
18241
18242 /* Hangup all interfaces if they have an owner */
18244 for (p = iflist; p; p = p->next) {
18245 if (p->owner)
18247 }
18249
18252 pthread_cancel(monitor_thread);
18253 pthread_kill(monitor_thread, SIGURG);
18254 pthread_join(monitor_thread, NULL);
18255 }
18258
18260
18261#if defined(HAVE_PRI)
18262 for (i = 0; i < NUM_SPANS; i++) {
18263 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
18264 pthread_join(pris[i].pri.master, NULL);
18265 }
18266 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
18267 dahdi_close_pri_fd(&(pris[i]), j);
18268 }
18269 sig_pri_stop_pri(&pris[i].pri);
18270 }
18271#if defined(HAVE_PRI_CCSS)
18272 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
18273 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
18274#endif /* defined(HAVE_PRI_CCSS) */
18276#endif
18277
18278#if defined(HAVE_SS7)
18279 for (i = 0; i < NUM_SPANS; i++) {
18280 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
18281 pthread_join(linksets[i].ss7.master, NULL);
18282 }
18283 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
18284 dahdi_close_ss7_fd(&(linksets[i]), j);
18285 }
18286 if (linksets[i].ss7.ss7) {
18287 ss7_destroy(linksets[i].ss7.ss7);
18288 linksets[i].ss7.ss7 = NULL;
18289 }
18290 }
18291#endif /* defined(HAVE_SS7) */
18293
18295
18298 STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
18299 return 0;
18300}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
void dahdi_native_unload(void)
void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
Unregister a set of monitor callbacks with the core.
Definition: ccss.c:1201
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition: ccss.c:1238
static ast_mutex_t iflock
Protect the interface list (of dahdi_pvt's)
Definition: chan_dahdi.c:816
#define NUM_SPANS
Definition: chan_dahdi.c:744
static struct dahdi_pvt * iflist
Definition: chan_dahdi.c:992
static ast_cond_t ss_thread_complete
Definition: chan_dahdi.c:832
static ast_mutex_t monlock
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing some...
Definition: chan_dahdi.c:827
static struct ast_channel_tech dahdi_tech
Definition: chan_dahdi.c:1227
static struct ast_custom_function polarity_function
Definition: chan_dahdi.c:2985
static struct ast_cli_entry dahdi_cli[]
Definition: chan_dahdi.c:16801
static pthread_t monitor_thread
This is the thread for the monitor which checks for input on the channels which are not currently in ...
Definition: chan_dahdi.c:831
static void destroy_all_channels(void)
Definition: chan_dahdi.c:5995
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2500
@ AST_SOFTHANGUP_APPUNLOAD
Definition: channel.h:1163
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7697
#define ast_cond_destroy(cond)
Definition: lock.h:206
#define AST_PTHREADT_NULL
Definition: lock.h:70
#define AST_PTHREADT_STOP
Definition: lock.h:71
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
void sig_pri_unload(void)
#define SIG_PRI_NUM_DCHANS
Definition: sig_pri.h:239
void sig_pri_stop_pri(struct sig_pri_span *pri)
#define SIG_SS7_NUM_DCHANS
Definition: sig_ss7.h:56
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515
struct ast_format_cap * capabilities
Definition: channel.h:652
struct dahdi_pvt * next
Definition: chan_dahdi.h:169
#define ARRAY_LEN(a)
Definition: utils.h:666

References ao2_cleanup, ARRAY_LEN, ast_cc_agent_unregister(), ast_cc_monitor_unregister(), ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy, ast_custom_function_unregister(), ast_manager_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), ast_channel_tech::capabilities, dahdi_cli, dahdi_native_unload(), dahdi_tech, destroy_all_channels(), iflist, iflock, sig_pri_span::master, sig_ss7_linkset::master, monitor_thread, monlock, dahdi_pvt::next, NULL, NUM_SPANS, dahdi_pvt::owner, polarity_function, SIG_PRI_NUM_DCHANS, sig_pri_stop_pri(), sig_pri_unload(), SIG_SS7_NUM_DCHANS, sig_ss7_linkset::ss7, ss_thread_complete, and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by load_module(), and unload_module().

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 20615 of file chan_dahdi.c.

◆ _dahdi_get_index()

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

Definition at line 3762 of file chan_dahdi.c.

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

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

◆ action_dahdidialoffhook()

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

Definition at line 16954 of file chan_dahdi.c.

16955{
16956 struct dahdi_pvt *p;
16957 const char *channel = astman_get_header(m, "DAHDIChannel");
16958 const char *number = astman_get_header(m, "Number");
16959 int i;
16960
16961 if (ast_strlen_zero(channel)) {
16962 astman_send_error(s, m, "No channel specified");
16963 return 0;
16964 }
16965 if (ast_strlen_zero(number)) {
16966 astman_send_error(s, m, "No number specified");
16967 return 0;
16968 }
16970 if (!p) {
16971 astman_send_error(s, m, "No such channel");
16972 return 0;
16973 }
16974 if (!p->owner) {
16975 astman_send_error(s, m, "Channel does not have it's owner");
16976 return 0;
16977 }
16978 for (i = 0; i < strlen(number); i++) {
16979 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16980 dahdi_queue_frame(p, &f);
16981 }
16982 astman_send_ack(s, m, "DAHDIDialOffhook");
16983 return 0;
16984}
static struct dahdi_pvt * find_channel_from_str(const char *channel)
Definition: chan_dahdi.c:16858
static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
Definition: chan_dahdi.c:3819
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1986
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2018
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1647
#define AST_FRAME_DTMF
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Number structure.
Definition: app_followme.c:157

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

Referenced by load_module().

◆ action_dahdidndoff()

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

Definition at line 16889 of file chan_dahdi.c.

16890{
16891 struct dahdi_pvt *p;
16892 const char *channel = astman_get_header(m, "DAHDIChannel");
16893
16894 if (ast_strlen_zero(channel)) {
16895 astman_send_error(s, m, "No channel specified");
16896 return 0;
16897 }
16899 if (!p) {
16900 astman_send_error(s, m, "No such channel");
16901 return 0;
16902 }
16903 dahdi_dnd(p, 0);
16904 astman_send_ack(s, m, "DND Disabled");
16905 return 0;
16906}
static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
Definition: chan_dahdi.c:9916

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

16871{
16872 struct dahdi_pvt *p;
16873 const char *channel = astman_get_header(m, "DAHDIChannel");
16874
16875 if (ast_strlen_zero(channel)) {
16876 astman_send_error(s, m, "No channel specified");
16877 return 0;
16878 }
16880 if (!p) {
16881 astman_send_error(s, m, "No such channel");
16882 return 0;
16883 }
16884 dahdi_dnd(p, 1);
16885 astman_send_ack(s, m, "DND Enabled");
16886 return 0;
16887}

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

16060{
16061 if (dahdi_restart() != 0) {
16062 astman_send_error(s, m, "Failed rereading DAHDI configuration");
16063 return 1;
16064 }
16065 astman_send_ack(s, m, "DAHDIRestart: Success");
16066 return 0;
16067}
static int dahdi_restart(void)
Definition: chan_dahdi.c:15921

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

16987{
16988 struct dahdi_pvt *tmp = NULL;
16989 const char *id = astman_get_header(m, "ActionID");
16990 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16991 char idText[256];
16992 int channels = 0;
16993 int dahdichanquery;
16994
16995 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16996 /* Not numeric string. */
16997 dahdichanquery = -1;
16998 }
16999
17000 idText[0] = '\0';
17001 if (!ast_strlen_zero(id)) {
17002 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
17003 }
17004
17005 astman_send_listack(s, m, "DAHDI channel status will follow", "start");
17006
17008
17009 for (tmp = iflist; tmp; tmp = tmp->next) {
17010 if (tmp->channel > 0) {
17011 int alm;
17012
17013 /* If a specific channel is queried for, only deliver status for that channel */
17014 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
17015 continue;
17016
17017 alm = get_alarms(tmp);
17018 channels++;
17019 if (tmp->owner) {
17020 /* Add data if we have a current call */
17021 astman_append(s,
17022 "Event: DAHDIShowChannels\r\n"
17023 "DAHDIChannel: %d\r\n"
17024 "Channel: %s\r\n"
17025 "Uniqueid: %s\r\n"
17026 "AccountCode: %s\r\n"
17027 "Signalling: %s\r\n"
17028 "SignallingCode: %d\r\n"
17029 "Context: %s\r\n"
17030 "DND: %s\r\n"
17031 "Alarm: %s\r\n"
17032 "Description: %s\r\n"
17033 "%s"
17034 "\r\n",
17035 tmp->channel,
17036 ast_channel_name(tmp->owner),
17039 sig2str(tmp->sig),
17040 tmp->sig,
17041 tmp->context,
17042 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
17043 alarm2str(alm),
17044 tmp->description, idText);
17045 } else {
17046 astman_append(s,
17047 "Event: DAHDIShowChannels\r\n"
17048 "DAHDIChannel: %d\r\n"
17049 "Signalling: %s\r\n"
17050 "SignallingCode: %d\r\n"
17051 "Context: %s\r\n"
17052 "DND: %s\r\n"
17053 "Alarm: %s\r\n"
17054 "Description: %s\r\n"
17055 "%s"
17056 "\r\n",
17057 tmp->channel, sig2str(tmp->sig), tmp->sig,
17058 tmp->context,
17059 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
17060 alarm2str(alm),
17061 tmp->description, idText);
17062 }
17063 }
17064 }
17065
17067
17068 astman_send_list_complete_start(s, m, "DAHDIShowChannelsComplete", channels);
17069 astman_append(s, "Items: %d\r\n", channels);
17071 return 0;
17072}
static char * alarm2str(int alm)
Definition: chan_dahdi.c:4702
#define sig2str
Definition: chan_dahdi.c:4785
static int get_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7637
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char * ast_channel_accountcode(const struct ast_channel *chan)
static struct channel_usage channels
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:2028
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:2064
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2072
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1907
char description[32]
A description for the channel configuration.
Definition: chan_dahdi.h:498
char context[AST_MAX_CONTEXT]
The configured context for incoming calls.
Definition: chan_dahdi.h:493

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

17075{
17076 const char *id = astman_get_header(m, "ActionID");
17077 int span;
17078 int res;
17079 char alarmstr[50];
17080 int ctl;
17081 char idText[256];
17082 int numspans = 0;
17083 struct dahdi_spaninfo spaninfo;
17084
17085 ctl = open("/dev/dahdi/ctl", O_RDWR);
17086 if (ctl < 0) {
17087 astman_send_error(s, m, "No DAHDI detected");
17088 return 0;
17089 }
17090
17091 idText[0] = '\0';
17092 if (!ast_strlen_zero(id)) {
17093 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
17094 }
17095 astman_send_listack(s, m, "DAHDI span statuses will follow", "start");
17096
17097 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
17098 spaninfo.spanno = span;
17099 res = ioctl(ctl, DAHDI_SPANSTAT, &spaninfo);
17100 if (res) {
17101 continue;
17102 }
17103 numspans++;
17104 build_alarm_info(alarmstr, &spaninfo);
17105 astman_append(s,
17106 "Event: DAHDIShowStatus\r\n"
17107 "Span: %d\r\n"
17108 "Description: %s\r\n"
17109 "Alarms: %s\r\n"
17110 "IRQ: %d\r\n"
17111 "bpviol: %d\r\n"
17112 "CRC: %d\r\n"
17113 "Framing: %s\r\n"
17114 "Coding: %s\r\n"
17115 "Options: %s\r\n"
17116 "LBO: %s\r\n"
17117 "%s"
17118 "\r\n",
17119 span, spaninfo.desc, alarmstr, spaninfo.irqmisses, spaninfo.bpvcount, spaninfo.crc4count,
17120 spaninfo.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
17121 spaninfo.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
17122 spaninfo.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
17123 "CAS",
17124 spaninfo.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
17125 spaninfo.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
17126 spaninfo.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
17127 "Unk",
17128 spaninfo.lineconfig & DAHDI_CONFIG_CRC4 ?
17129 spaninfo.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
17130 spaninfo.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
17131 lbostr[spaninfo.lbo],
17132 idText);
17133 }
17134 close(ctl);
17135
17136 astman_send_list_complete_start(s, m, "DAHDIShowStatusComplete", numspans);
17137 astman_append(s, "Items: %d\r\n", numspans);
17139 return 0;
17140}
static void build_alarm_info(char *restrict alarmstr, struct dahdi_spaninfo *spaninfo)
Definition: chan_dahdi.c:16389
static const char *const lbostr[]
Definition: chan_dahdi.c:675

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

Referenced by load_module().

◆ action_transfer()

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

Definition at line 16908 of file chan_dahdi.c.

16909{
16910 struct dahdi_pvt *p;
16911 const char *channel = astman_get_header(m, "DAHDIChannel");
16912
16913 if (ast_strlen_zero(channel)) {
16914 astman_send_error(s, m, "No channel specified");
16915 return 0;
16916 }
16918 if (!p) {
16919 astman_send_error(s, m, "No such channel");
16920 return 0;
16921 }
16922 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16923 astman_send_error(s, m, "Channel signaling is not analog");
16924 return 0;
16925 }
16927 astman_send_ack(s, m, "DAHDITransfer");
16928 return 0;
16929}
#define TRANSFER
Definition: chan_dahdi.c:16816
static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
Definition: chan_dahdi.c:16819
static int dahdi_analog_lib_handles(int signalling, int radio, int oprmode)
Definition: chan_dahdi.h:843

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

16932{
16933 struct dahdi_pvt *p;
16934 const char *channel = astman_get_header(m, "DAHDIChannel");
16935
16936 if (ast_strlen_zero(channel)) {
16937 astman_send_error(s, m, "No channel specified");
16938 return 0;
16939 }
16941 if (!p) {
16942 astman_send_error(s, m, "No such channel");
16943 return 0;
16944 }
16945 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16946 astman_send_error(s, m, "Channel signaling is not analog");
16947 return 0;
16948 }
16950 astman_send_ack(s, m, "DAHDIHangup");
16951 return 0;
16952}
#define HANGUP
Definition: chan_dahdi.c:16817

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

Referenced by load_module().

◆ alarm2str()

static char * alarm2str ( int  alm)
static

Definition at line 4702 of file chan_dahdi.c.

4703{
4704 int x;
4705 for (x = 0; x < ARRAY_LEN(alarms); x++) {
4706 if (alarms[x].alarm & alm)
4707 return alarms[x].name;
4708 }
4709 return alm ? "Unknown Alarm" : "No Alarm";
4710}
int alarm
Definition: chan_dahdi.c:4690
static struct @114 alarms[]

References alarm, alarms, and ARRAY_LEN.

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

◆ alloc_sub()

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

Definition at line 4497 of file chan_dahdi.c.

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

References ast_debug, ast_log, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_close_sub(), dahdi_open(), dahdi_subchannel::dfd, errno, LOG_WARNING, subnames, and dahdi_pvt::subs.

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

◆ analog_ss_thread()

static void * analog_ss_thread ( void *  data)
static

Definition at line 9962 of file chan_dahdi.c.

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

References alloc_sub(), ao2_cleanup, ao2_ref, ARRAY_LEN, ast_canmatch_extension(), ast_channel_bridge_peer(), ast_channel_caller(), ast_channel_cleanup, ast_channel_context(), ast_channel_context_set(), ast_channel_exten_set(), ast_channel_flags(), ast_channel_get_bridge_channel(), ast_channel_language(), ast_channel_lock, ast_channel_name(), ast_channel_rings_set(), ast_channel_tech(), ast_channel_tech_pvt(), ast_channel_unlock, ast_clear_flag, ast_cond_signal, ast_copy_string(), ast_debug, ast_dsp_digitreset(), ast_dsp_free(), ast_dsp_set_digitmode(), ast_exists_extension(), AST_FLAG_END_DTMF_ONLY, AST_FRAME_DTMF, ast_frfree, ast_get_chan_features_pickup_config(), ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log, ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_parking_blind_transfer_park(), ast_parking_is_exten_park(), ast_parking_provider_registered(), ast_party_name_free(), ast_party_name_init(), ast_party_number_free(), ast_party_number_init(), ast_pbx_run(), ast_pickup_call(), ast_queue_unhold(), ast_read(), ast_remaining_ms(), ast_safe_sleep(), ast_set_callerid(), ast_set_flag, ast_setstate(), ast_shrink_phone_number(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_tvnow(), ast_verb, ast_waitfor(), ast_waitfordigit(), ast_waitstream(), buf, bump_gains(), dahdi_pvt::call_forward, callerid_feed(), callerid_feed_jp(), callerid_free(), callerid_get(), callerid_get_dtmf(), callerid_new(), ast_smdi_md_message::calling_st, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::cancallforward, canmatch_featurecode(), dahdi_pvt::canpark, ast_bridge_channel::chan, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, CID_START_POLARITY_IN, CID_START_RING, dahdi_pvt::context, ringContextData::contextData, dahdi_dnd(), dahdi_ec_enable(), dahdi_get_event(), dahdi_get_index, dahdi_set_hook(), dahdi_setlinear(), dahdi_tech, dahdi_wait_event(), dahdi_wink(), ast_channel::data, dahdi_pvt::defcontext, dahdi_subchannel::dfd, distinctiveringaftercid, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), dahdi_pvt::exten, dahdi_pvt::firstdigit_timeout, ast_frame::flags, ast_frame::frametype, ast_smdi_md_message::fwd_st, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_pvt::interdigit_timeout, ISTRUNK, len(), dahdi_subchannel::linear, dahdi_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::matchdigit_timeout, my_getsigstr(), my_handle_notify_message(), name, NEED_MFDETECT, NULL, dahdi_subchannel::owner, dahdi_pvt::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, RAII_VAR, distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_COR, S_OR, ast_frame::samples, dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, ss_thread_complete, ss_thread_count, ss_thread_lock, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), dahdi_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), dahdi_pvt::use_callerid, dahdi_pvt::use_smdi, and dahdi_pvt::usedistinctiveringdetection.

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

◆ analog_tone_to_dahditone()

static int analog_tone_to_dahditone ( enum analog_tone  tone)
static

Definition at line 1303 of file chan_dahdi.c.

1304{
1305 switch (tone) {
1307 return DAHDI_TONE_RINGTONE;
1309 return DAHDI_TONE_STUTTER;
1311 return DAHDI_TONE_CONGESTION;
1313 return DAHDI_TONE_DIALTONE;
1315 return DAHDI_TONE_DIALRECALL;
1316 case ANALOG_TONE_INFO:
1317 return DAHDI_TONE_INFO;
1318 default:
1319 return -1;
1320 }
1321}
@ ANALOG_TONE_CONGESTION
Definition: sig_analog.h:73
@ ANALOG_TONE_INFO
Definition: sig_analog.h:76
@ ANALOG_TONE_DIALTONE
Definition: sig_analog.h:74
@ ANALOG_TONE_DIALRECALL
Definition: sig_analog.h:75
@ ANALOG_TONE_STUTTER
Definition: sig_analog.h:72
@ ANALOG_TONE_RINGTONE
Definition: sig_analog.h:71

References ANALOG_TONE_CONGESTION, ANALOG_TONE_DIALRECALL, ANALOG_TONE_DIALTONE, ANALOG_TONE_INFO, ANALOG_TONE_RINGTONE, and ANALOG_TONE_STUTTER.

Referenced by my_play_tone().

◆ analogsub_to_dahdisub()

static int analogsub_to_dahdisub ( enum analog_sub  analogsub)
static

Definition at line 1323 of file chan_dahdi.c.

1324{
1325 int index;
1326
1327 switch (analogsub) {
1328 case ANALOG_SUB_REAL:
1329 index = SUB_REAL;
1330 break;
1332 index = SUB_CALLWAIT;
1333 break;
1335 index = SUB_THREEWAY;
1336 break;
1337 default:
1338 ast_log(LOG_ERROR, "Unidentified sub!\n");
1339 index = SUB_REAL;
1340 }
1341
1342 return index;
1343}
@ ANALOG_SUB_THREEWAY
Definition: sig_analog.h:111
@ ANALOG_SUB_REAL
Definition: sig_analog.h:109
@ ANALOG_SUB_CALLWAIT
Definition: sig_analog.h:110

References ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL, ANALOG_SUB_THREEWAY, ast_log, LOG_ERROR, SUB_CALLWAIT, SUB_REAL, and SUB_THREEWAY.

Referenced by my_allocate_sub(), my_conf_add(), my_conf_del(), my_get_sub_fd(), my_handle_dtmf(), my_is_dialing(), my_new_analog_ast_channel(), my_play_tone(), my_set_inthreeway(), my_set_linear_mode(), my_swap_subchannels(), my_unallocate_sub(), and my_wink().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 20615 of file chan_dahdi.c.

◆ attempt_transfer()

static int attempt_transfer ( struct dahdi_pvt p)
static

Definition at line 7578 of file chan_dahdi.c.

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

13553{
13554 struct dahdi_pvt *p = *pvt;
13555
13556 if (p->inalarm)
13557 return 0;
13558
13559 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode))
13560 return analog_available(p->sig_pvt);
13561
13562 switch (p->sig) {
13563#if defined(HAVE_PRI)
13565 {
13566 struct sig_pri_chan *pvt_chan;
13567 int res;
13568
13569 pvt_chan = p->sig_pvt;
13570 res = sig_pri_available(&pvt_chan, is_specific_channel);
13571 *pvt = pvt_chan->chan_pvt;
13572 return res;
13573 }
13574#endif /* defined(HAVE_PRI) */
13575#if defined(HAVE_SS7)
13576 case SIG_SS7:
13577 return sig_ss7_available(p->sig_pvt);
13578#endif /* defined(HAVE_SS7) */
13579 default:
13580 break;
13581 }
13582
13583 if (p->locallyblocked || p->remotelyblocked) {
13584 return 0;
13585 }
13586
13587 /* If no owner definitely available */
13588 if (!p->owner) {
13589#ifdef HAVE_OPENR2
13590 /* Trust MFC/R2 */
13591 if (p->mfcr2) {
13592 if (p->mfcr2call) {
13593 return 0;
13594 } else {
13595 return 1;
13596 }
13597 }
13598#endif
13599 return 1;
13600 }
13601
13602 return 0;
13603}
#define SIG_PRI_LIB_HANDLE_CASES
Definition: chan_dahdi.h:813
#define SIG_SS7
Definition: chan_dahdi.h:807
int analog_available(struct analog_pvt *p)
Definition: sig_analog.c:793
int sig_pri_available(struct sig_pri_chan **pvt, int is_specific_channel)
int sig_ss7_available(struct sig_ss7_chan *p)
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: chan_dahdi.h:453
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked. 1 maintenance, 2 blocked in hardware.
Definition: chan_dahdi.h:462
void * sig_pvt
Definition: chan_dahdi.h:766
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 16389 of file chan_dahdi.c.

16390{
16391 alarmstr[0] = '\0';
16392 if (spaninfo->alarms > 0) {
16393 if (spaninfo->alarms & DAHDI_ALARM_BLUE) {
16394 strcat(alarmstr, "BLU/");
16395 }
16396 if (spaninfo->alarms & DAHDI_ALARM_YELLOW) {
16397 strcat(alarmstr, "YEL/");
16398 }
16399 if (spaninfo->alarms & DAHDI_ALARM_RED) {
16400 strcat(alarmstr, "RED/");
16401 }
16402 if (spaninfo->alarms & DAHDI_ALARM_LOOPBACK) {
16403 strcat(alarmstr, "LB/");
16404 }
16405 if (spaninfo->alarms & DAHDI_ALARM_RECOVER) {
16406 strcat(alarmstr, "REC/");
16407 }
16408 if (spaninfo->alarms & DAHDI_ALARM_NOTOPEN) {
16409 strcat(alarmstr, "NOP/");
16410 }
16411 if (!strlen(alarmstr)) {
16412 strcat(alarmstr, "UUU/");
16413 }
16414 if (strlen(alarmstr)) {
16415 /* Strip trailing / */
16416 alarmstr[strlen(alarmstr) - 1] = '\0';
16417 }
16418 } else {
16419 if (spaninfo->numchans) {
16420 strcpy(alarmstr, "OK");
16421 } else {
16422 strcpy(alarmstr, "UNCONFIGURED");
16423 }
16424 }
16425}

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

18319{
18320 char *c, *chan;
18321 int x, start, finish;
18322 struct dahdi_pvt *tmp;
18323
18324 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
18325 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
18326 return -1;
18327 }
18328
18329 c = ast_strdupa(value);
18330
18331 while ((chan = strsep(&c, ","))) {
18332 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
18333 /* Range */
18334 } else if (sscanf(chan, "%30d", &start)) {
18335 /* Just one */
18336 finish = start;
18337 } else if (!strcasecmp(chan, "pseudo")) {
18338 finish = start = CHAN_PSEUDO;
18339 } else {
18340 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
18341 return -1;
18342 }
18343 if (finish < start) {
18344 ast_log(LOG_WARNING, "Silliness: %d < %d\n", start, finish);
18345 x = finish;
18346 finish = start;
18347 start = x;
18348 }
18349
18350 for (x = start; x <= finish; x++) {
18351 if (conf->wanted_channels_start &&
18352 (x < conf->wanted_channels_start ||
18353 x > conf->wanted_channels_end)
18354 ) {
18355 continue;
18356 }
18357 tmp = mkintf(x, conf, reload);
18358
18359 if (tmp) {
18360 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
18361 } else {
18362 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
18363 (reload == 1) ? "reconfigure" : "register", value);
18364 return -1;
18365 }
18366 if (x == CHAN_PSEUDO) {
18367 has_pseudo = 1;
18368 }
18369 }
18370 }
18371
18372 return 0;
18373}
static struct dahdi_pvt * mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
Definition: chan_dahdi.c:12571
static int has_pseudo
Definition: chan_dahdi.c:758
static int reload(void)
Definition: chan_dahdi.c:20591
#define CHAN_PSEUDO
Definition: chan_dahdi.c:747
All configuration options for http media cache.
int value
Definition: syslog.c:37
static struct test_val c

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

Referenced by process_dahdi().

◆ bump_gains()

static int bump_gains ( struct dahdi_pvt p)
static

Definition at line 5225 of file chan_dahdi.c.

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

11163{
11164 int x;
11165 int sum = 0;
11166
11167 if (!len)
11168 return 0;
11169
11170 for (x = 0; x < len; x++)
11171 sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11172
11173 return sum / len;
11174}
#define AST_ALAW(a)
Definition: alaw.h:84
#define abs(x)
Definition: f2c.h:195
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
#define AST_MULAW(a)
Definition: ulaw.h:85

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

Referenced by do_monitor(), and mwi_thread().

◆ canmatch_featurecode()

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

Definition at line 9935 of file chan_dahdi.c.

9936{
9937 int extlen = strlen(exten);
9938
9939 if (!extlen) {
9940 return 1;
9941 }
9942
9943 if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
9944 return 1;
9945 }
9946 /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
9947 if (exten[0] == '*' && extlen < 3) {
9948 if (extlen == 1) {
9949 return 1;
9950 }
9951 /* "*0" should be processed before it gets here */
9952 switch (exten[1]) {
9953 case '6':
9954 case '7':
9955 case '8':
9956 return 1;
9957 }
9958 }
9959 return 0;
9960}

Referenced by analog_ss_thread().

◆ check_for_conference()

static int check_for_conference ( struct dahdi_pvt p)
static

Definition at line 7611 of file chan_dahdi.c.

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

References ast_log, ast_verb, dahdi_pvt::channel, dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::master, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_handle_event(), and my_check_for_conference().

◆ conf_add()

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

Definition at line 4787 of file chan_dahdi.c.

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

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

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

◆ conf_del()

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

Definition at line 4836 of file chan_dahdi.c.

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

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

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

◆ create_channel_name()

static struct ast_str * create_channel_name ( struct dahdi_pvt i)
static

Definition at line 9549 of file chan_dahdi.c.

9551{
9552 struct ast_str *chan_name;
9553 int x, y;
9554
9555 /* Create the new channel name tail. */
9556 if (!(chan_name = ast_str_create(32))) {
9557 return NULL;
9558 }
9559 if (i->channel == CHAN_PSEUDO) {
9560 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
9561#if defined(HAVE_PRI)
9562 } else if (i->pri) {
9563 ast_mutex_lock(&i->pri->lock);
9564 y = ++i->pri->new_chan_seq;
9565 if (is_outgoing) {
9566 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
9567 address[0] = '\0';
9568 } else if (ast_strlen_zero(i->cid_subaddr)) {
9569 /* Put in caller-id number only since there is no subaddress. */
9570 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
9571 } else {
9572 /* Put in caller-id number and subaddress. */
9573 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
9574 i->cid_subaddr, (unsigned)y);
9575 }
9576 ast_mutex_unlock(&i->pri->lock);
9577#endif /* defined(HAVE_PRI) */
9578 } else {
9579 y = 1;
9580 do {
9581 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
9582 for (x = 0; x < 3; ++x) {
9583 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
9584 ast_channel_name(i->subs[x].owner) + 6)) {
9585 break;
9586 }
9587 }
9588 ++y;
9589 } while (x < 3);
9590 }
9591 return chan_name;
9592}
char * address
Definition: f2c.h:59
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
Support for dynamic strings.
Definition: strings.h:623
char cid_subaddr[AST_MAX_EXTENSION]
Caller ID subaddress from an incoming call.
Definition: chan_dahdi.h:539
long int ast_random(void)
Definition: utils.c:2312

References ast_channel_name(), ast_mutex_lock, ast_mutex_unlock, ast_random(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_strlen_zero(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::lock, NULL, dahdi_subchannel::owner, dahdi_pvt::span, and dahdi_pvt::subs.

Referenced by dahdi_cc_callback(), and dahdi_new().

◆ dahdi_ami_channel_event()

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

Definition at line 2038 of file chan_dahdi.c.

2039{
2040 char ch_name[23];
2041
2042 if (p->channel < CHAN_PSEUDO) {
2043 /* No B channel */
2044 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
2045 } else if (p->channel == CHAN_PSEUDO) {
2046 /* Pseudo channel */
2047 strcpy(ch_name, "pseudo");
2048 } else {
2049 /* Real channel */
2050 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
2051 }
2052 publish_dahdichannel(chan, p->group, p->span, ch_name);
2053}
static void publish_dahdichannel(struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages.
Definition: chan_dahdi.c:2011
ast_group_t group
Bitmapped groups this belongs to.
Definition: chan_dahdi.h:554

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

Referenced by dahdi_new().

◆ dahdi_answer()

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

Definition at line 6769 of file chan_dahdi.c.

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

References analog_answer(), ast_channel_tech_pvt(), ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_UP, dahdi_pvt::channel, dahdi_analog_lib_handles(), dahdi_get_index, dahdi_pvt::lock, LOG_WARNING, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, SIG_MFCR2, sig_pri_answer(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_answer(), and SUB_REAL.

◆ dahdi_call()

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

Definition at line 5463 of file chan_dahdi.c.

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

References analog_call(), args, AST_APP_ARG, ast_channel_connected(), ast_channel_name(), ast_channel_tech_pvt(), ast_channel_transfercapability(), ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_log, ast_mutex_lock, ast_mutex_unlock, AST_NONSTANDARD_APP_ARGS, ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_UP, ast_strdupa, c, dahdi_pvt::callwaitrings, dahdi_pvt::channel, dahdi_analog_lib_handles(), dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, errno, ext, dahdi_pvt::exten, dahdi_pvt::hidecallerid, ast_party_connected_line::id, IS_DIGITAL, dahdi_pvt::law, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, dahdi_subchannel::needbusy, NULL, ast_party_id::number, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::radio, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_gain(), dahdi_pvt::sig, SIG_MFCR2, sig_pri_call(), sig_pri_extract_called_num_subaddr(), dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_call(), ast_party_number::str, dahdi_pvt::stripmsd, SUB_REAL, dahdi_pvt::subs, dahdi_pvt::txdrc, dahdi_pvt::txgain, ast_party_number::valid, and dahdi_pvt::waitingfordt.

◆ dahdi_callwait()

static int dahdi_callwait ( struct ast_channel ast)
static

Definition at line 5429 of file chan_dahdi.c.

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

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

14227{
14228 struct dahdi_pvt *p;
14229 struct dahdi_pvt *exitpvt;
14230 struct dahdi_starting_point start;
14231 int groupmatched = 0;
14232 int channelmatched = 0;
14233
14235 p = determine_starting_point(dest, &start);
14236 if (!p) {
14238 return -1;
14239 }
14240 exitpvt = p;
14241 for (;;) {
14242 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
14243 /* We found a potential match. call the callback */
14244 struct ast_str *device_name;
14245 char *dash;
14246 const char *monitor_type;
14247 char dialstring[AST_CHANNEL_NAME];
14248 char full_device_name[AST_CHANNEL_NAME];
14249
14252 break;
14256#if defined(HAVE_PRI)
14258 /*
14259 * ISDN is in a trunk busy condition so we need to monitor
14260 * the span congestion device state.
14261 */
14262 snprintf(full_device_name, sizeof(full_device_name),
14263 "DAHDI/I%d/congestion", p->pri->span);
14264 } else
14265#endif /* defined(HAVE_PRI) */
14266 {
14267#if defined(HAVE_PRI)
14268 device_name = create_channel_name(p, 1, "");
14269#else
14270 device_name = create_channel_name(p);
14271#endif /* defined(HAVE_PRI) */
14272 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14273 device_name ? ast_str_buffer(device_name) : "");
14274 ast_free(device_name);
14275 /*
14276 * The portion after the '-' in the channel name is either a random
14277 * number, a sequence number, or a subchannel number. None are
14278 * necessary so strip them off.
14279 */
14280 dash = strrchr(full_device_name, '-');
14281 if (dash) {
14282 *dash = '\0';
14283 }
14284 }
14285 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14286
14287 /*
14288 * Analog can only do generic monitoring.
14289 * ISDN is in a trunk busy condition and any "device" is going
14290 * to be busy until a B channel becomes available. The generic
14291 * monitor can do this task.
14292 */
14293 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14294 callback(inbound,
14295#if defined(HAVE_PRI)
14296 p->pri ? p->pri->cc_params : p->cc_params,
14297#else
14298 p->cc_params,
14299#endif /* defined(HAVE_PRI) */
14300 monitor_type, full_device_name, dialstring, NULL);
14301 break;
14302 }
14303 }
14304 p = start.backwards ? p->prev : p->next;
14305 if (!p) {
14306 p = start.backwards ? ifend : iflist;
14307 }
14308 if (p == exitpvt) {
14309 break;
14310 }
14311 }
14313 return 0;
14314}
#define AST_CC_GENERIC_MONITOR_TYPE
Definition: ccss.h:455
@ AST_CC_MONITOR_NEVER
Definition: ccss.h:76
@ AST_CC_MONITOR_ALWAYS
Definition: ccss.h:87
@ AST_CC_MONITOR_NATIVE
Definition: ccss.h:78
@ AST_CC_MONITOR_GENERIC
Definition: ccss.h:83
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
Definition: ccss.c:882
static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
Definition: chan_dahdi.c:13519
static struct ast_str * create_channel_name(struct dahdi_pvt *i)
Definition: chan_dahdi.c:9549
static struct dahdi_pvt * ifend
Definition: chan_dahdi.c:993
static struct dahdi_pvt * determine_starting_point(const char *data, struct dahdi_starting_point *param)
Definition: chan_dahdi.c:13822
#define AST_CHANNEL_NAME
Definition: channel.h:173
struct dahdi_pvt * prev
Definition: chan_dahdi.h:170
struct ast_cc_config_params * cc_params
Definition: chan_dahdi.h:767

References AST_CC_GENERIC_MONITOR_TYPE, AST_CC_MONITOR_ALWAYS, AST_CC_MONITOR_GENERIC, AST_CC_MONITOR_NATIVE, AST_CC_MONITOR_NEVER, AST_CHANNEL_NAME, ast_free, ast_get_cc_monitor_policy(), ast_mutex_lock, ast_mutex_unlock, ast_str_buffer(), dahdi_starting_point::backwards, dahdi_pvt::cc_params, dahdi_starting_point::channelmatch, create_channel_name(), dahdi_sig_pri_lib_handles(), determine_starting_point(), dahdi_starting_point::groupmatch, ifend, iflist, iflock, is_group_or_channel_match(), dahdi_pvt::next, NULL, dahdi_pvt::prev, dahdi_pvt::sig, dahdi_starting_point::span, and dahdi_pvt::span.

◆ dahdi_chan_conf_default()

static struct dahdi_chan_conf dahdi_chan_conf_default ( void  )
static

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

Definition at line 1060 of file chan_dahdi.c.

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

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

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

◆ dahdi_close()

static void dahdi_close ( int  fd)
static

Definition at line 4463 of file chan_dahdi.c.

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

Referenced by dahdi_close_sub().

◆ dahdi_close_sub()

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

Definition at line 4469 of file chan_dahdi.c.

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

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

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

◆ dahdi_conf_update()

void dahdi_conf_update ( struct dahdi_pvt p)

Definition at line 4913 of file chan_dahdi.c.

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

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

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

◆ dahdi_confmute()

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

Definition at line 5269 of file chan_dahdi.c.

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

References ast_log, dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_handle_dtmf(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_read(), my_confmute(), and my_handle_dtmf().

◆ dahdi_create_channel_range()

static int dahdi_create_channel_range ( int  start,
int  end 
)
static

Definition at line 11600 of file chan_dahdi.c.

11601{
11602 struct dahdi_pvt *cur;
11603 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
11604 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
11606 int ret = RESULT_FAILURE; /* be pessimistic */
11607
11608 ast_debug(1, "channel range caps: %d - %d\n", start, end);
11610 for (cur = iflist; cur; cur = cur->next) {
11611 if (cur->channel >= start && cur->channel <= end) {
11613 "channel range %d-%d is occupied\n",
11614 start, end);
11615 goto out;
11616 }
11617 }
11618#ifdef HAVE_PRI
11619 {
11620 int i, x;
11621 for (x = 0; x < NUM_SPANS; x++) {
11622 struct dahdi_pri *pri = pris + x;
11623
11624 if (!pris[x].pri.pvts[0]) {
11625 break;
11626 }
11627 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
11628 int channo = pri->dchannels[i];
11629
11630 if (!channo) {
11631 break;
11632 }
11633 if (!pri->pri.fds[i]) {
11634 break;
11635 }
11636 if (channo >= start && channo <= end) {
11638 "channel range %d-%d is occupied by span %d\n",
11639 start, end, x + 1);
11640 goto out;
11641 }
11642 }
11643 }
11644 }
11645#endif
11646 if (!default_conf.chan.cc_params || !base_conf.chan.cc_params ||
11647 !conf.chan.cc_params) {
11648 goto out;
11649 }
11650 default_conf.wanted_channels_start = start;
11651 base_conf.wanted_channels_start = start;
11652 conf.wanted_channels_start = start;
11653 default_conf.wanted_channels_end = end;
11654 base_conf.wanted_channels_end = end;
11655 conf.wanted_channels_end = end;
11656 if (setup_dahdi_int(0, &default_conf, &base_conf, &conf) == 0) {
11657 ret = RESULT_SUCCESS;
11658 }
11659out:
11662 ast_cc_config_params_destroy(conf.chan.cc_params);
11664 return ret;
11665}
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition: ccss.c:698
static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
Definition: chan_dahdi.c:20038
static struct dahdi_chan_conf dahdi_chan_conf_default(void)
Definition: chan_dahdi.c:1060
#define RESULT_SUCCESS
Definition: cli.h:40
#define RESULT_FAILURE
Definition: cli.h:42
char * end
Definition: eagi_proxy.c:73
int wanted_channels_end
Don't create channels above this number (infinity by default)
Definition: chan_dahdi.c:1056
struct dahdi_pvt chan
Definition: chan_dahdi.c:1023
int wanted_channels_start
Don't create channels below this number.
Definition: chan_dahdi.c:1050
FILE * out
Definition: utils/frame.c:33

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

Referenced by dahdi_create_channels().

◆ dahdi_create_channels()

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

Definition at line 15844 of file chan_dahdi.c.

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

11519{
11520 struct dahdi_pvt *cur;
11521 struct dahdi_pvt *next;
11522 int destroyed_first = 0;
11523 int destroyed_last = 0;
11524
11526 ast_debug(1, "range: %d-%d\n", start, end);
11527 for (cur = iflist; cur; cur = next) {
11528 next = cur->next;
11529 if (cur->channel >= start && cur->channel <= end) {
11530 int x = DAHDI_FLASH;
11531
11532 if (cur->channel > destroyed_last) {
11533 destroyed_last = cur->channel;
11534 }
11535 if (destroyed_first < 1 || cur->channel < destroyed_first) {
11536 destroyed_first = cur->channel;
11537 }
11538 ast_debug(3, "Destroying %d\n", cur->channel);
11539 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11540 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11541
11542 destroy_channel(cur, 1);
11544 }
11545 }
11547 if (destroyed_first > start || destroyed_last < end) {
11548 ast_debug(1, "Asked to destroy %d-%d, destroyed %d-%d,\n",
11549 start, end, destroyed_first, destroyed_last);
11550 }
11551}
static void destroy_channel(struct dahdi_pvt *cur, int now)
Definition: chan_dahdi.c:5977
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
struct ast_module * self
Definition: module.h:356

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

Referenced by dahdi_destroy_channels(), and do_monitor().

◆ dahdi_destroy_channels()

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

Definition at line 15800 of file chan_dahdi.c.

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

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

14165{
14166#if defined(HAVE_PRI)
14167 const char *device;
14168 unsigned span;
14169 int res;
14170
14171 device = data;
14172
14173 if (*device != 'I') {
14174 /* The request is not for an ISDN span device. */
14175 return AST_DEVICE_UNKNOWN;
14176 }
14177 res = sscanf(device, "I%30u", &span);
14178 if (res != 1 || !span || NUM_SPANS < span) {
14179 /* Bad format for ISDN span device name. */
14180 return AST_DEVICE_UNKNOWN;
14181 }
14182 device = strchr(device, '/');
14183 if (!device) {
14184 /* Bad format for ISDN span device name. */
14185 return AST_DEVICE_UNKNOWN;
14186 }
14187
14188 /*
14189 * Since there are currently no other span devstate's defined,
14190 * it must be congestion.
14191 */
14192#if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14193 ++device;
14194 if (!strcmp(device, "congestion"))
14195#endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14196 {
14197 return pris[span - 1].pri.congestion_devstate;
14198 }
14199#if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14200 else if (!strcmp(device, "threshold")) {
14201 return pris[span - 1].pri.threshold_devstate;
14202 }
14203 return AST_DEVICE_UNKNOWN;
14204#endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14205#else
14206 return AST_DEVICE_UNKNOWN;
14207#endif /* defined(HAVE_PRI) */
14208}
@ AST_DEVICE_UNKNOWN
Definition: devicestate.h:53

References AST_DEVICE_UNKNOWN, and NUM_SPANS.

◆ dahdi_dial_str()

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

Definition at line 1420 of file chan_dahdi.c.

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

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

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

◆ dahdi_digit_begin()

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

Definition at line 4567 of file chan_dahdi.c.

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

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

◆ dahdi_digit_end()

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

Definition at line 4629 of file chan_dahdi.c.

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

References ast_channel_name(), ast_channel_tech_pvt(), ast_debug, ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::begindigit, dahdi_get_index, dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::dialing, digit, dahdi_pvt::lock, out, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.

◆ dahdi_dnd()

static int dahdi_dnd ( struct dahdi_pvt dahdichan,
int  flag 
)
static

enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel

Parameters
dahdichan"Physical" DAHDI channel (e.g: DAHDI/5)
flagon 1 to enable, 0 to disable, -1 return dnd value

chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical DAHDI channel). Use this to enable or disable it.

Bug:
the use of the word "channel" for those dahdichans is really confusing.

Definition at line 9916 of file chan_dahdi.c.

9917{
9918 if (dahdi_analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
9919 return analog_dnd(dahdichan->sig_pvt, flag);
9920 }
9921
9922 if (flag == -1) {
9923 return dahdichan->dnd;
9924 }
9925
9926 /* Do not disturb */
9927 dahdichan->dnd = flag;
9928 ast_verb(3, "%s DND on channel %d\n",
9929 flag? "Enabled" : "Disabled",
9930 dahdichan->channel);
9931 publish_dnd_state(dahdichan->channel, flag ? "enabled" : "disabled");
9932 return 0;
9933}
static void publish_dnd_state(int channel, const char *status)
Definition: chan_dahdi.c:9887
long int flag
Definition: f2c.h:83
int analog_dnd(struct analog_pvt *p, int flag)
Definition: sig_analog.c:4191
unsigned int dnd
TRUE if Do-Not-Disturb is enabled, present only for non sig_analog.
Definition: chan_dahdi.h:262

References analog_dnd(), ast_verb, dahdi_pvt::channel, dahdi_analog_lib_handles(), dahdi_pvt::dnd, dahdi_pvt::oprmode, publish_dnd_state(), dahdi_pvt::radio, dahdi_pvt::sig, and dahdi_pvt::sig_pvt.

Referenced by action_dahdidndoff(), action_dahdidndon(), action_dahdishowchannels(), analog_ss_thread(), dahdi_set_dnd(), and dahdi_show_channel().

◆ dahdi_dtmf_detect_disable()

void dahdi_dtmf_detect_disable ( struct dahdi_pvt p)

Definition at line 6833 of file chan_dahdi.c.

6834{
6835 int val = 0;
6836
6837 p->ignoredtmf = 1;
6838
6839 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6840
6841 if (!p->hardwaredtmf && p->dsp) {
6842 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
6844 }
6845}
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1768
unsigned int ignoredtmf
TRUE if DTMF detection is disabled.
Definition: chan_dahdi.h:310
int dsp_features
DSP feature flags: DSP_FEATURE_xxx.
Definition: chan_dahdi.h:740
Definition: ast_expr2.c:325

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

Referenced by dahdi_setoption(), and native_start().

◆ dahdi_dtmf_detect_enable()

void dahdi_dtmf_detect_enable ( struct dahdi_pvt p)

Definition at line 6847 of file chan_dahdi.c.

6848{
6849 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
6850
6851 if (p->channel == CHAN_PSEUDO)
6852 return;
6853
6854 p->ignoredtmf = 0;
6855
6856 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6857
6858 if (!p->hardwaredtmf && p->dsp) {
6861 }
6862}
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28

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

Referenced by dahdi_setoption(), and native_stop().

◆ dahdi_ec_disable()

void dahdi_ec_disable ( struct dahdi_pvt p)

Definition at line 5040 of file chan_dahdi.c.

5041{
5042 int res;
5043
5044 if (p->echocanon) {
5045 struct dahdi_echocanparams ecp = { .tap_length = 0 };
5046
5047 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
5048
5049 if (res)
5050 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
5051 else
5052 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
5053 }
5054
5055 p->echocanon = 0;
5056}
unsigned int echocanon
TRUE if echo cancellation is turned on.
Definition: chan_dahdi.h:272

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

Referenced by __dahdi_exception(), dahdi_func_write(), dahdi_handle_event(), dahdi_hangup(), dahdi_setoption(), handle_init_event(), my_set_echocanceller(), and native_start().

◆ dahdi_ec_enable()

void dahdi_ec_enable ( struct dahdi_pvt p)

Definition at line 4968 of file chan_dahdi.c.

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

References ast_debug, ast_log, dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::head, LOG_WARNING, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_func_write(), dahdi_handle_event(), dahdi_setoption(), handle_init_event(), my_set_echocanceller(), and native_stop().

◆ dahdi_exception()

static struct ast_frame * dahdi_exception ( struct ast_channel ast)
static

Definition at line 8843 of file chan_dahdi.c.

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

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

16820{
16821 if (p) {
16822 switch (mode) {
16823 case TRANSFER:
16824 p->fake_event = DAHDI_EVENT_WINKFLASH;
16825 break;
16826 case HANGUP:
16827 p->fake_event = DAHDI_EVENT_ONHOOK;
16828 break;
16829 default:
16830 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));
16831 }
16832 }
16833 return 0;
16834}

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

Referenced by action_transfer(), and action_transferhangup().

◆ dahdi_fixup()

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

Definition at line 7494 of file chan_dahdi.c.

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

References analog_fixup(), ast_channel_name(), ast_channel_tech_pvt(), AST_CONTROL_RINGING, ast_debug, ast_mutex_lock, ast_mutex_unlock, AST_STATE_RINGING, dahdi_pvt::channel, dahdi_analog_lib_handles(), dahdi_conf_update(), dahdi_indicate(), dahdi_master_slave_unlink(), dahdi_sig_pri_lib_handles(), dahdi_pvt::lock, NULL, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, sig_pri_fixup(), dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_fixup(), and dahdi_pvt::subs.

◆ dahdi_func_read()

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

Definition at line 7132 of file chan_dahdi.c.

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

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

◆ dahdi_func_write()

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

Definition at line 7301 of file chan_dahdi.c.

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

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

◆ dahdi_get_event()

static int dahdi_get_event ( int  fd)
inlinestatic

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 843 of file chan_dahdi.c.

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

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

◆ dahdi_handle_dtmf()

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

Definition at line 7664 of file chan_dahdi.c.

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

References ast_async_goto(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_unlock, AST_CONTROL_ANSWER, ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_verb, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::callprogress, CALLPROGRESS_FAX, dahdi_pvt::callwaitcas, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_subchannel::dfd, dahdi_pvt::dsp, dahdi_pvt::dsp_features, errno, dahdi_subchannel::f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxhandled, ast_frame::frametype, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, NULL, pbx_builtin_setvar_helper(), S_COR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, and dahdi_pvt::usefaxbuffers.

Referenced by dahdi_handle_event(), and dahdi_read().

◆ dahdi_handle_event()

static struct ast_frame * dahdi_handle_event ( struct ast_channel ast)
static

Definition at line 7819 of file chan_dahdi.c.

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

References alloc_sub(), analog_ss_thread(), ast_party_caller::ani, ast_party_caller::ani2, dahdi_pvt::answeronpolarityswitch, ast_callid_threadstorage_auto(), ast_callid_threadstorage_auto_clean(), AST_CAUSE_NO_ANSWER, ast_channel_caller(), ast_channel_lock, ast_channel_name(), ast_channel_pbx(), ast_channel_rings_set(), ast_channel_softhangup_internal_flag_add(), ast_channel_tech_pvt(), ast_channel_trylock, ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, ast_copy_string(), ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_null_frame, ast_pthread_create_detached, ast_queue_hangup_with_cause(), ast_queue_hold(), ast_queue_unhold(), ast_setstate(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, attempt_transfer(), c, dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, CANPROGRESSDETECT, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, check_for_conference(), dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_conf_update(), dahdi_confmute(), dahdi_dial_str(), dahdi_ec_disable(), dahdi_ec_enable(), dahdi_get_event(), dahdi_get_index, dahdi_handle_dtmf(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_ring_phone(), dahdi_set_hook(), dahdi_sig_pri_lib_handles(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, DLA_LOCK, DLA_UNLOCK, dahdi_pvt::dop, dahdi_pvt::dsp, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), dahdi_subchannel::f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), ast_party_caller::id, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, ast_party_id::name, dahdi_subchannel::needanswer, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, NULL, ast_party_id::number, ast_frame::offset, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::radio, restore_conference(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_COR, ast_frame::samples, save_conference(), dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI_CALL_LEVEL_PROCEEDING, sig_pri_chan_alarm_notify(), sig_pri_dial_complete(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sig_ss7_set_alarm(), ast_frame::src, ast_party_name::str, ast_party_number::str, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), dahdi_pvt::threewaycalling, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, unalloc_sub(), ast_party_name::valid, ast_party_number::valid, dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.

Referenced by __dahdi_exception().

◆ dahdi_hangup()

static int dahdi_hangup ( struct ast_channel ast)
static

Definition at line 6320 of file chan_dahdi.c.

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

References analog_hangup(), ast_channel_hangupcause(), ast_channel_name(), ast_channel_setoption(), ast_channel_tech_pvt(), ast_channel_tech_pvt_set(), ast_copy_string(), ast_debug, ast_dsp_free(), ast_dsp_set_digitmode(), ast_free, ast_log, ast_module_unref, ast_mutex_lock, ast_mutex_unlock, AST_OPTION_AUDIO_MODE, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_queue_hold(), ast_queue_unhold(), AST_STATE_RESERVED, AST_STATE_UP, ast_verb, dahdi_pvt::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cid_tag, dahdi_pvt::cidcwexpire, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_analog_lib_handles(), dahdi_conf_update(), dahdi_confmute(), dahdi_ec_disable(), dahdi_get_index, dahdi_set_hook(), dahdi_setlinear(), dahdi_sig_pri_lib_handles(), dahdi_pvt::destroy, destroy_channel(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::didtdd, dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::doreoriginate, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, analog_pvt::fxsoffhookstate, dahdi_pvt::guardtime, dahdi_pvt::hidecallerid, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_pvt::law, dahdi_pvt::law_default, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_WARNING, dahdi_pvt::mohsuggest, dahdi_pvt::muting, my_is_off_hook(), my_off_hook(), my_play_tone(), dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, NULL, num_restart_pending, dahdi_pvt::oprmode, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_subchannel::owner, dahdi_pvt::owner, pbx_builtin_getvar_helper(), dahdi_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, dahdi_pvt::polarity, POLARITY_IDLE, dahdi_pvt::pulsedial, dahdi_pvt::radio, dahdi_pvt::rdnis, dahdi_pvt::reoriginate, reset_conf(), restart_monitor(), dahdi_pvt::restartpending, restore_gains(), revert_fax_buffers(), dahdi_pvt::ringt, ast_module_info::self, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, sig_pri_hangup(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_hangup(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), unalloc_sub(), and dahdi_pvt::waitingfordt.

◆ dahdi_iflist_extract()

static void dahdi_iflist_extract ( struct dahdi_pvt pvt)
static

Definition at line 5670 of file chan_dahdi.c.

5671{
5672 /* Extract from the forward chain. */
5673 if (pvt->prev) {
5674 pvt->prev->next = pvt->next;
5675 } else if (iflist == pvt) {
5676 /* Node is at the head of the list. */
5677 iflist = pvt->next;
5678 }
5679
5680 /* Extract from the reverse chain. */
5681 if (pvt->next) {
5682 pvt->next->prev = pvt->prev;
5683 } else if (ifend == pvt) {
5684 /* Node is at the end of the list. */
5685 ifend = pvt->prev;
5686 }
5687
5688 /* Node is no longer in the list. */
5690 pvt->prev = NULL;
5691 pvt->next = NULL;
5692}
@ DAHDI_IFLIST_NONE
Definition: chan_dahdi.h:117
enum DAHDI_IFLIST which_iflist
Definition: chan_dahdi.h:168

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

Referenced by destroy_dahdi_pvt().

◆ dahdi_iflist_insert()

static void dahdi_iflist_insert ( struct dahdi_pvt pvt)
static

Definition at line 5622 of file chan_dahdi.c.

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

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

Referenced by duplicate_pseudo(), and mkintf().

◆ dahdi_indicate()

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

Definition at line 9422 of file chan_dahdi.c.

9423{
9424 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9425 int res=-1;
9426 int idx;
9427 int func = DAHDI_FLASH;
9428
9429 ast_mutex_lock(&p->lock);
9430 ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
9431 switch (p->sig) {
9432#if defined(HAVE_PRI)
9434 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
9436 return res;
9437#endif /* defined(HAVE_PRI) */
9438#if defined(HAVE_SS7)
9439 case SIG_SS7:
9440 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
9442 return res;
9443#endif /* defined(HAVE_SS7) */
9444 default:
9445 break;
9446 }
9447#ifdef HAVE_OPENR2
9448 if (p->mfcr2 && !p->mfcr2_call_accepted) {
9450 /* if this is an R2 call and the call is not yet accepted, we don't want the
9451 tone indications to mess up with the MF tones */
9452 return 0;
9453 }
9454#endif
9455 idx = dahdi_get_index(chan, p, 0);
9456 if (idx == SUB_REAL) {
9457 switch (condition) {
9458 case AST_CONTROL_BUSY:
9459 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
9460 break;
9462 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
9463
9464 if (ast_channel_state(chan) != AST_STATE_UP) {
9465 if ((ast_channel_state(chan) != AST_STATE_RING) ||
9466 ((p->sig != SIG_FXSKS) &&
9467 (p->sig != SIG_FXSLS) &&
9468 (p->sig != SIG_FXSGS))) {
9469 /* We're playing audible ringback tone on the channel,
9470 * so set state to AST_STATE_RING, not AST_STATE_RINGING. */
9472 }
9473 }
9474 break;
9476 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
9477 /* act as a progress or proceeding, allowing the caller to enter additional numbers */
9478 res = 0;
9479 break;
9481 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
9482 /* don't continue in ast_indicate */
9483 res = 0;
9484 break;
9486 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
9487 /* don't continue in ast_indicate */
9488 res = 0;
9489 break;
9491 /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
9492 switch (ast_channel_hangupcause(chan)) {
9495 case 0:/* Cause has not been set. */
9496 /* Supply a more appropriate cause. */
9498 break;
9499 default:
9500 break;
9501 }
9502 break;
9503 case AST_CONTROL_HOLD:
9504 ast_moh_start(chan, data, p->mohinterpret);
9505 break;
9506 case AST_CONTROL_UNHOLD:
9507 ast_moh_stop(chan);
9508 break;
9510 if (p->radio)
9511 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
9512 res = 0;
9513 break;
9515 if (p->radio)
9516 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
9517 res = 0;
9518 break;
9519 case AST_CONTROL_FLASH:
9520 /* flash hookswitch */
9521 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
9522 /* Clear out the dial buffer */
9523 p->dop.dialstr[0] = '\0';
9524 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
9525 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
9526 ast_channel_name(chan), strerror(errno));
9527 } else
9528 res = 0;
9529 } else
9530 res = 0;
9531 break;
9533 res = 0;
9534 break;
9535 case -1:
9536 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9537 break;
9538 }
9539 } else {
9540 res = 0;
9541 }
9543 return res;
9544}
#define AST_CAUSE_CONGESTION
Definition: causes.h:153
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:106
#define AST_CAUSE_USER_BUSY
Definition: causes.h:107
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
@ AST_CONTROL_SRCUPDATE
@ AST_CONTROL_PROGRESS
@ AST_CONTROL_BUSY
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_PROCEEDING
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_HOLD
@ AST_CONTROL_FLASH
@ AST_CONTROL_INCOMPLETE
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:7787
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7797
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:514

References AST_CAUSE_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_USER_BUSY, ast_channel_hangupcause(), ast_channel_hangupcause_set(), ast_channel_name(), ast_channel_tech_pvt(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_log, ast_moh_start(), ast_moh_stop(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_RING, AST_STATE_UP, dahdi_get_index, dahdi_set_hook(), dahdi_subchannel::dfd, dahdi_pvt::dop, errno, ISTRUNK, dahdi_pvt::lock, LOG_WARNING, dahdi_pvt::mohinterpret, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, sig_pri_indicate(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_indicate(), SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_fixup().

◆ dahdi_lock_sub_owner()

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

Definition at line 3794 of file chan_dahdi.c.

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

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

Referenced by wakeup_sub().

◆ dahdi_master_slave_link()

void dahdi_master_slave_link ( struct dahdi_pvt slave,
struct dahdi_pvt master 
)

Definition at line 7470 of file chan_dahdi.c.

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

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

Referenced by native_start().

◆ dahdi_master_slave_unlink()

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

Definition at line 7414 of file chan_dahdi.c.

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

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

9604{
9605 struct ast_channel *tmp;
9606 struct ast_format_cap *caps;
9607 struct ast_format *deflaw;
9608 int x;
9609 int features;
9610 struct ast_str *chan_name;
9611 struct ast_variable *v;
9612 char *dashptr;
9613 char device_name[AST_CHANNEL_NAME];
9614
9615 if (i->subs[idx].owner) {
9616 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
9617 return NULL;
9618 }
9619
9620#if defined(HAVE_PRI)
9621 /*
9622 * The dnid has been stuffed with the called-number[:subaddress]
9623 * by dahdi_request() for outgoing calls.
9624 */
9625 chan_name = create_channel_name(i, i->outgoing, i->dnid);
9626#else
9627 chan_name = create_channel_name(i);
9628#endif /* defined(HAVE_PRI) */
9629 if (!chan_name) {
9630 return NULL;
9631 }
9632
9634 if (!caps) {
9635 ast_free(chan_name);
9636 return NULL;
9637 }
9638
9639 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));
9640 ast_free(chan_name);
9641 if (!tmp) {
9642 ao2_ref(caps, -1);
9643 return NULL;
9644 }
9645
9647
9648 if (callid) {
9649 ast_channel_callid_set(tmp, callid);
9650 }
9651
9653#if defined(HAVE_PRI)
9654 if (i->pri) {
9656 }
9657#endif /* defined(HAVE_PRI) */
9659 if (law) {
9660 i->law = law;
9661 if (law == DAHDI_LAW_ALAW) {
9662 deflaw = ast_format_alaw;
9663 } else {
9664 deflaw = ast_format_ulaw;
9665 }
9666 } else {
9667 switch (i->sig) {
9669 /* Make sure companding law is known. */
9670 i->law = (i->law_default == DAHDI_LAW_ALAW)
9671 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
9672 break;
9673 default:
9674 i->law = i->law_default;
9675 break;
9676 }
9677 if (i->law_default == DAHDI_LAW_ALAW) {
9678 deflaw = ast_format_alaw;
9679 } else {
9680 deflaw = ast_format_ulaw;
9681 }
9682 }
9683 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
9684 ast_format_cap_append(caps, deflaw, 0);
9686 ao2_ref(caps, -1);
9687 /* Start out assuming ulaw since it's smaller :) */
9688 ast_channel_set_rawreadformat(tmp, deflaw);
9689 ast_channel_set_readformat(tmp, deflaw);
9690 ast_channel_set_rawwriteformat(tmp, deflaw);
9691 ast_channel_set_writeformat(tmp, deflaw);
9692 i->subs[idx].linear = 0;
9693 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
9694 features = 0;
9695 if (idx == SUB_REAL) {
9696 if (i->busydetect && CANBUSYDETECT(i))
9697 features |= DSP_FEATURE_BUSY_DETECT;
9699 features |= DSP_FEATURE_CALL_PROGRESS;
9701 features |= DSP_FEATURE_WAITDIALTONE;
9702 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
9704 features |= DSP_FEATURE_FAX_DETECT;
9705 }
9706 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
9707 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
9708 i->hardwaredtmf = 0;
9709 features |= DSP_FEATURE_DIGIT_DETECT;
9710 } else if (NEED_MFDETECT(i)) {
9711 i->hardwaredtmf = 1;
9712 features |= DSP_FEATURE_DIGIT_DETECT;
9713 }
9714 }
9715 if (features) {
9716 if (i->dsp) {
9717 ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
9718 } else {
9719 if (i->channel != CHAN_PSEUDO)
9720 i->dsp = ast_dsp_new();
9721 else
9722 i->dsp = NULL;
9723 if (i->dsp) {
9724 i->dsp_features = features;
9725#if defined(HAVE_PRI) || defined(HAVE_SS7)
9726 /* We cannot do progress detection until receive PROGRESS message */
9727 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
9728 /* Remember requested DSP features, don't treat
9729 talking as ANSWER */
9730 i->dsp_features = features & ~DSP_PROGRESS_TALK;
9731 features = 0;
9732 }
9733#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9734 ast_dsp_set_features(i->dsp, features);
9738 if (i->busydetect && CANBUSYDETECT(i)) {
9741 }
9742 }
9743 }
9744 }
9745
9747
9748 if (state == AST_STATE_RING)
9749 ast_channel_rings_set(tmp, 1);
9751 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
9752 /* Only FXO signalled stuff can be picked up */
9757 }
9758 if (!ast_strlen_zero(i->parkinglot))
9759 ast_channel_parkinglot_set(tmp, i->parkinglot);
9760 if (!ast_strlen_zero(i->language))
9761 ast_channel_language_set(tmp, i->language);
9762 if (!i->owner)
9763 i->owner = tmp;
9765 ast_channel_accountcode_set(tmp, i->accountcode);
9766 if (i->amaflags)
9768 i->subs[idx].owner = tmp;
9770 if (!dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
9771 ast_channel_call_forward_set(tmp, i->call_forward);
9772 }
9773 /* If we've been told "no ADSI" then enforce it */
9774 if (!i->adsi)
9776 if (!ast_strlen_zero(i->exten))
9778 if (!ast_strlen_zero(i->rdnis)) {
9781 }
9782 if (!ast_strlen_zero(i->dnid)) {
9784 }
9785
9786 /* Don't use ast_set_callerid() here because it will
9787 * generate a needless NewCallerID event */
9788#if defined(HAVE_PRI) || defined(HAVE_SS7)
9789 if (!ast_strlen_zero(i->cid_ani)) {
9791 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_ani);
9792 } else if (!ast_strlen_zero(i->cid_num)) {
9795 }
9796#else
9797 if (!ast_strlen_zero(i->cid_num)) {
9800 }
9801#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9805 ast_channel_caller(tmp)->ani2 = i->cid_ani2;
9807 /* clear the fake event in case we posted one before we had ast_channel */
9808 i->fake_event = 0;
9809 /* Assure there is no confmute on this channel */
9810 dahdi_confmute(i, 0);
9811 i->muting = 0;
9812 /* Configure the new channel jb */
9814
9815 /* Set initial device state */
9816 ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
9817 dashptr = strrchr(device_name, '-');
9818 if (dashptr) {
9819 *dashptr = '\0';
9820 }
9823
9824 for (v = i->vars ; v ; v = v->next)
9826
9828
9829 ast_channel_unlock(tmp);
9830
9832
9834 if (startpbx) {
9835#ifdef HAVE_OPENR2
9836 if (i->mfcr2call) {
9837 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
9838 }
9839#endif
9840 if (ast_pbx_start(tmp)) {
9841 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
9842 ast_hangup(tmp);
9843 return NULL;
9844 }
9845 }
9846 return tmp;
9847}
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
Definition: abstract_jb.c:593
void ast_cc_copy_config_params(struct ast_cc_config_params *dest, const struct ast_cc_config_params *src)
copy CCSS configuration parameters from one structure to another
Definition: ccss.c:860
#define CALLPROGRESS_FAX_INCOMING
Definition: chan_dahdi.c:751
#define CALLPROGRESS_FAX_OUTGOING
Definition: chan_dahdi.c:750
static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
Definition: chan_dahdi.c:2038
static struct ast_jb_conf global_jbconf
Definition: chan_dahdi.c:696
static char progzone[10]
Definition: chan_dahdi.c:796
#define CANBUSYDETECT(p)
Definition: chan_dahdi.c:784
void ast_channel_named_pickupgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1299
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
int ast_channel_cc_params_init(struct ast_channel *chan, const struct ast_cc_config_params *base_params)
Set up datastore with CCSS parameters for a channel.
Definition: channel.c:10477
@ AST_ADSI_UNAVAILABLE
Definition: channel.h:891
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
void ast_channel_named_callgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
@ AST_FLAG_DISABLE_DEVSTATE_CACHE
Definition: channel.h:1049
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2455
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
@ AST_DEVSTATE_NOT_CACHABLE
Definition: devicestate.h:69
int ast_devstate_changed_literal(enum ast_device_state state, enum ast_devstate_cache cachable, const char *device)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:474
#define DSP_FEATURE_WAITDIALTONE
Definition: dsp.h:44
#define DSP_FEATURE_BUSY_DETECT
Definition: dsp.h:27
void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, const struct ast_dsp_busy_pattern *cadence)
Set expected lengths of the busy tone.
Definition: dsp.c:1804
#define DSP_FEATURE_FAX_DETECT
Definition: dsp.h:29
#define DSP_FEATURE_CALL_PROGRESS
Definition: dsp.h:43
void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
Set number of required cadences for busy.
Definition: dsp.c:1793
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1758
int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
Set zone for doing progress detection.
Definition: dsp.c:1892
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:457
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4723
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Definition of a media format.
Definition: format.c:43
struct ast_party_dialed::@210 number
Dialed/Called number.
char * str
Subscriber phone number (Malloced)
Definition: channel.h:388
char * tag
User-set "tag".
Definition: channel.h:356
int presentation
Q.931 encoded presentation-indicator encoded field.
Definition: channel.h:279
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:297
int plan
Q.931 Type-Of-Number and Numbering-Plan encoded fields.
Definition: channel.h:295
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:529
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
struct ast_variable * vars
Channel variable list with associated values to set when a channel is created.
Definition: chan_dahdi.h:586
int busycount
Number of times to see "busy" tone before hanging up.
Definition: chan_dahdi.h:643
int waitfordialtone
Number of milliseconds to wait for dialtone.
Definition: chan_dahdi.h:658
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:672
char dnid[AST_MAX_EXTENSION]
Dialed Number Identifier.
Definition: chan_dahdi.h:549
struct ast_namedgroups * named_pickupgroups
Named pickup groups this belongs to.
Definition: chan_dahdi.h:581
int cid_ani2
Automatic Number Identification code from PRI.
Definition: chan_dahdi.h:526
struct ast_namedgroups * named_callgroups
Named call groups this belongs to.
Definition: chan_dahdi.h:576
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:571
int callingpres
Definition: chan_dahdi.h:594
char parkinglot[AST_MAX_EXTENSION]
Definition: chan_dahdi.h:520
int amaflags
Definition: chan_dahdi.h:703
char language[MAX_LANGUAGE]
Language configured for calls.
Definition: chan_dahdi.h:509
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_dahdi.h:702
struct ast_dsp_busy_pattern busy_cadence
Busy cadence pattern description.
Definition: chan_dahdi.h:648
ast_group_t callgroup
Bitmapped call groups this belongs to.
Definition: chan_dahdi.h:566
int dialtone_detect
Number of frames to watch for dialtone in incoming calls.
Definition: chan_dahdi.h:671
int cid_ton
Caller ID Q.931 TON/NPI field values. Set by PRI. Zero otherwise.
Definition: chan_dahdi.h:535

References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, ast_party_caller::ani, ast_party_caller::ani2, ao2_ref, AST_ADSI_UNAVAILABLE, ast_cc_copy_config_params(), ast_channel_adsicpe_set(), ast_channel_alloc, ast_channel_amaflags_set(), ast_channel_caller(), ast_channel_callgroup_set(), ast_channel_callid_set(), ast_channel_cc_params_init(), ast_channel_context_set(), ast_channel_dialed(), ast_channel_exten_set(), ast_channel_flags(), AST_CHANNEL_NAME, ast_channel_name(), ast_channel_named_callgroups_set(), ast_channel_named_pickupgroups_set(), ast_channel_nativeformats_set(), ast_channel_pickupgroup_set(), ast_channel_redirecting(), ast_channel_rings_set(), ast_channel_set_fd(), ast_channel_set_rawreadformat(), ast_channel_set_rawwriteformat(), ast_channel_set_readformat(), ast_channel_set_writeformat(), ast_channel_stage_snapshot(), ast_channel_stage_snapshot_done(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_unlock, ast_copy_string(), ast_debug, AST_DEVICE_UNKNOWN, ast_devstate_changed_literal(), AST_DEVSTATE_NOT_CACHABLE, ast_dsp_new(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_digitmode(), ast_dsp_set_features(), AST_FLAG_DISABLE_DEVSTATE_CACHE, ast_format_alaw, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_ulaw, ast_free, ast_hangup(), ast_jb_configure(), ast_log, ast_module_ref, ast_pbx_start(), ast_set_flag, AST_STATE_RING, ast_str_buffer(), ast_strdup, ast_strlen_zero(), dahdi_pvt::busy_cadence, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::call_forward, dahdi_pvt::callgroup, dahdi_pvt::callingpres, dahdi_pvt::callprogress, CALLPROGRESS_FAX_INCOMING, CALLPROGRESS_FAX_OUTGOING, CALLPROGRESS_PROGRESS, CANBUSYDETECT, CANPROGRESSDETECT, dahdi_pvt::cc_params, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::cid_ani2, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_tag, dahdi_pvt::cid_ton, dahdi_pvt::context, create_channel_name(), dahdi_ami_channel_event(), dahdi_analog_lib_handles(), dahdi_confmute(), dahdi_setlinear(), dahdi_sig_pri_lib_handles(), dahdi_tech, dahdi_subchannel::dfd, dahdi_pvt::dialtone_detect, dahdi_pvt::dialtone_scanning_time_elapsed, dahdi_pvt::dnid, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, DSP_FEATURE_WAITDIALTONE, dahdi_pvt::dsp_features, dahdi_pvt::dtmfrelax, dahdi_pvt::exten, dahdi_pvt::fake_event, ast_party_redirecting::from, global_jbconf, dahdi_pvt::hardwaredtmf, ast_party_caller::id, dahdi_pvt::language, dahdi_pvt::law, dahdi_pvt::law_default, dahdi_subchannel::linear, LOG_WARNING, dahdi_pvt::muting, ast_party_id::name, ast_variable::name, dahdi_pvt::named_callgroups, dahdi_pvt::named_pickupgroups, NEED_MFDETECT, ast_variable::next, NULL, ast_party_id::number, ast_party_dialed::number, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::parkinglot, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_party_number::plan, ast_party_name::presentation, ast_party_number::presentation, progzone, dahdi_pvt::radio, dahdi_pvt::rdnis, ast_module_info::self, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_PRI_LIB_HANDLE_CASES, SIG_SS7, ast_party_number::str, ast_party_dialed::str, SUB_REAL, subnames, dahdi_pvt::subs, ast_party_id::tag, ast_party_number::valid, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

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

◆ dahdi_new_callid_clean()

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

Definition at line 9594 of file chan_dahdi.c.

9595{
9596 struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, assignedids, requestor, callid);
9597
9599
9600 return new_channel;
9601}

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

Referenced by my_new_analog_ast_channel().

◆ dahdi_open()

static int dahdi_open ( char *  fn)
static

Definition at line 4416 of file chan_dahdi.c.

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

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

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

◆ dahdi_queryoption()

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

Definition at line 6864 of file chan_dahdi.c.

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

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

◆ dahdi_queue_frame()

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

Definition at line 3819 of file chan_dahdi.c.

3820{
3821 for (;;) {
3822 if (p->owner) {
3823 if (ast_channel_trylock(p->owner)) {
3825 } else {
3826 ast_queue_frame(p->owner, f);
3828 break;
3829 }
3830 } else
3831 break;
3832 }
3833}
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1158

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

Referenced by action_dahdidialoffhook().

◆ dahdi_read()

static struct ast_frame * dahdi_read ( struct ast_channel ast)
static

Definition at line 8858 of file chan_dahdi.c.

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

References __dahdi_exception(), ANALOG_DIALMODE_BOTH, ANALOG_DIALMODE_DTMF, analog_exception(), analog_handle_dtmf(), ast_channel_flags(), ast_channel_get_up_time(), ast_channel_name(), ast_channel_rawreadformat(), ast_channel_tech_pvt(), ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_debug, ast_dsp_get_tcount(), ast_dsp_get_tstate(), ast_dsp_process(), ast_dsp_set_features(), ast_dsp_was_muted(), AST_FLAG_BLOCKING, ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_slin, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_log, ast_mutex_trylock, ast_mutex_unlock, ast_null_frame, ast_queue_frame(), ast_setstate(), AST_STATE_DIALING, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, dahdi_subchannel::buffer, dahdi_pvt::busydetect, c, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, CHECK_BLOCKING, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidspill, dahdi_analog_lib_handles(), dahdi_callwait(), dahdi_confmute(), dahdi_dial_str(), dahdi_get_index, dahdi_handle_dtmf(), DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_setlinear(), dahdi_sig_pri_lib_handles(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dialmode, dahdi_pvt::dialtone_detect, dahdi_pvt::dialtone_scanning_time_elapsed, dahdi_pvt::dop, dahdi_pvt::dsp, DSP_FEATURE_FAX_DETECT, DSP_FEATURE_WAITDIALTONE, dahdi_pvt::dsp_features, DSP_TONE_STATE_DIALTONE, DSP_TONE_STATE_RINGING, errno, dahdi_subchannel::f, dahdi_pvt::fake_event, dahdi_pvt::faxdetect_timeout, dahdi_pvt::firstradio, ast_frame_subclass::format, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_subchannel::inthreeway, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, dahdi_pvt::muting, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, NULL, ast_frame::offset, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::owner, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::radio, READ_SIZE, restore_conference(), dahdi_pvt::ringt, ast_frame::samples, send_callerid(), dahdi_pvt::sig, SIG_PRI_CALL_LEVEL_PROCEEDING, dahdi_pvt::sig_pvt, ast_frame::src, SUB_CALLWAIT, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_feed(), dahdi_pvt::waitfordialtoneduration, and dahdi_pvt::waitingfordt.

◆ dahdi_request()

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

Definition at line 13983 of file chan_dahdi.c.

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

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

16037{
16038 switch (cmd) {
16039 case CLI_INIT:
16040 e->command = "dahdi restart";
16041 e->usage =
16042 "Usage: dahdi restart\n"
16043 " Restarts the DAHDI channels: destroys them all and then\n"
16044 " re-reads them from chan_dahdi.conf.\n"
16045 " Note that this will STOP any running CALL on DAHDI channels.\n"
16046 "";
16047 return NULL;
16048 case CLI_GENERATE:
16049 return NULL;
16050 }
16051 if (a->argc != 2)
16052 return CLI_SHOWUSAGE;
16053
16054 if (dahdi_restart() != 0)
16055 return CLI_FAILURE;
16056 return CLI_SUCCESS;
16057}

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

◆ dahdi_ring_phone()

static int dahdi_ring_phone ( struct dahdi_pvt p)
static

Definition at line 7534 of file chan_dahdi.c.

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

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

Referenced by __dahdi_exception(), dahdi_handle_event(), and my_ring().

◆ dahdi_sendtext()

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

Definition at line 20470 of file chan_dahdi.c.

20471{
20472#define END_SILENCE_LEN 400
20473#define HEADER_MS 50
20474#define TRAILER_MS 5
20475#define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
20476#define ASCII_BYTES_PER_CHAR 80
20477
20478 unsigned char *buf,*mybuf;
20479 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
20480 struct pollfd fds[1];
20481 int size,res,fd,len,x;
20482 int bytes=0;
20483 int idx;
20484
20485 /*
20486 * Initial carrier (imaginary)
20487 *
20488 * Note: The following float variables are used by the
20489 * PUT_CLID_MARKMS and PUT_CLID() macros.
20490 */
20491 float cr = 1.0;
20492 float ci = 0.0;
20493 float scont = 0.0;
20494
20495 if (!text[0]) {
20496 return(0); /* if nothing to send, don't */
20497 }
20498 idx = dahdi_get_index(c, p, 0);
20499 if (idx < 0) {
20500 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
20501 return -1;
20502 }
20503 if ((!p->tdd) && (!p->mate)) {
20504#if defined(HAVE_PRI)
20505#if defined(HAVE_PRI_DISPLAY_TEXT)
20506 ast_mutex_lock(&p->lock);
20508 sig_pri_sendtext(p->sig_pvt, text);
20509 }
20511#endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
20512#endif /* defined(HAVE_PRI) */
20513 return(0); /* if not in TDD mode, just return */
20514 }
20515 if (p->mate)
20517 else
20518 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
20519 if (!buf)
20520 return -1;
20521 mybuf = buf;
20522 if (p->mate) {
20523 /* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
20524 struct ast_format *codec = AST_LAW(p);
20525
20526 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
20528 }
20529 /* Put actual message */
20530 for (x = 0; text[x]; x++) {
20531 PUT_CLID(text[x]);
20532 }
20533 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
20535 }
20536 len = bytes;
20537 buf = mybuf;
20538 } else {
20539 len = tdd_generate(p->tdd, buf, text);
20540 if (len < 1) {
20541 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
20542 ast_free(mybuf);
20543 return -1;
20544 }
20545 }
20546 memset(buf + len, 0x7f, END_SILENCE_LEN);
20548 fd = p->subs[idx].dfd;
20549 while (len) {
20550 if (ast_check_hangup(c)) {
20551 ast_free(mybuf);
20552 return -1;
20553 }
20554 size = len;
20555 if (size > READ_SIZE)
20556 size = READ_SIZE;
20557 fds[0].fd = fd;
20558 fds[0].events = POLLOUT | POLLPRI;
20559 fds[0].revents = 0;
20560 res = poll(fds, 1, -1);
20561 if (!res) {
20562 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
20563 continue;
20564 }
20565 /* if got exception */
20566 if (fds[0].revents & POLLPRI) {
20567 ast_free(mybuf);
20568 return -1;
20569 }
20570 if (!(fds[0].revents & POLLOUT)) {
20571 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
20572 continue;
20573 }
20574 res = write(fd, buf, size);
20575 if (res != size) {
20576 if (res == -1) {
20577 ast_free(mybuf);
20578 return -1;
20579 }
20580 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
20581 break;
20582 }
20583 len -= size;
20584 buf += size;
20585 }
20586 ast_free(mybuf);
20587 return(0);
20588}
char * text
Definition: app_queue.c:1809
#define PUT_CLID(byte)
Definition: callerid.h:412
#define PUT_CLID_MARKMS
Definition: callerid.h:397
#define HEADER_MS
#define END_SILENCE_LEN
#define TRAILER_MS
#define ASCII_BYTES_PER_CHAR
#define HEADER_LEN
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
struct ast_codec * codec
Pointer to the codec in use for this format.
Definition: format.c:47
#define TDD_BYTES_PER_CHAR
Definition: tdd.h:27
int tdd_generate(struct tdd_state *tdd, unsigned char *buf, const char *string)
Definition: tdd.c:296

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

◆ dahdi_set_dnd()

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

Definition at line 16675 of file chan_dahdi.c.

16676{
16677 int channel;
16678 int on;
16679 struct dahdi_pvt *dahdi_chan = NULL;
16680
16681 switch (cmd) {
16682 case CLI_INIT:
16683 e->command = "dahdi set dnd";
16684 e->usage =
16685 "Usage: dahdi set dnd <chan#> <on|off>\n"
16686 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16687 " Changes take effect immediately.\n"
16688 " <chan num> is the channel number\n"
16689 " <on|off> Enable or disable DND mode?\n"
16690 ;
16691 return NULL;
16692 case CLI_GENERATE:
16693 return NULL;
16694 }
16695
16696 if (a->argc != 5)
16697 return CLI_SHOWUSAGE;
16698
16699 if ((channel = atoi(a->argv[3])) <= 0) {
16700 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16701 return CLI_SHOWUSAGE;
16702 }
16703
16704 if (ast_true(a->argv[4]))
16705 on = 1;
16706 else if (ast_false(a->argv[4]))
16707 on = 0;
16708 else {
16709 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16710 return CLI_SHOWUSAGE;
16711 }
16712
16714 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16715 if (dahdi_chan->channel != channel)
16716 continue;
16717
16718 /* Found the channel. Actually set it */
16719 dahdi_dnd(dahdi_chan, on);
16720 break;
16721 }
16723
16724 if (!dahdi_chan) {
16725 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16726 return CLI_FAILURE;
16727 }
16728
16729 return CLI_SUCCESS;
16730}
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition: utils.c:2216

References a, ast_cli(), ast_false(), ast_mutex_lock, ast_mutex_unlock, ast_true(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_dnd(), iflist, iflock, dahdi_pvt::next, NULL, and ast_cli_entry::usage.

◆ dahdi_set_hook()

static int dahdi_set_hook ( int  fd,
int  hs 
)
inlinestatic

Definition at line 5252 of file chan_dahdi.c.

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

References ast_log, errno, and LOG_WARNING.

Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_wink(), handle_init_event(), mkintf(), mwi_send_process_buffer(), mwi_send_process_event(), my_off_hook(), and my_on_hook().

◆ dahdi_set_hwgain()

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

Definition at line 16518 of file chan_dahdi.c.

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

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

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

References a, ast_cli(), ast_false(), ast_mutex_lock, ast_mutex_unlock, ast_true(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, iflist, iflock, dahdi_pvt::mwioverride_active, dahdi_pvt::mwioverride_disposition, dahdi_pvt::next, NULL, and ast_cli_entry::usage.

◆ dahdi_set_swgain()

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

Definition at line 16597 of file chan_dahdi.c.

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

References a, ast_cli(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_subchannel::dfd, iflist, iflock, dahdi_pvt::law, dahdi_pvt::next, NULL, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::txdrc, dahdi_pvt::txgain, and ast_cli_entry::usage.

◆ dahdi_setlinear()

static int dahdi_setlinear ( int  dfd,
int  linear 
)
static

Definition at line 4491 of file chan_dahdi.c.

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

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

◆ dahdi_setoption()

static int dahdi_setoption ( struct ast_channel chan,
int  option,
void *  data,
int  datalen 
)
static
Todo:
XXX This is an abuse of the stack!!

Definition at line 6913 of file chan_dahdi.c.

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

References ast_channel_name(), ast_channel_tech(), ast_channel_tech_pvt(), ast_check_hangup(), ast_debug, ast_dsp_set_digitmode(), ast_dsp_set_features(), ast_log, AST_OPTION_AUDIO_MODE, AST_OPTION_DIGIT_DETECT, AST_OPTION_ECHOCAN, AST_OPTION_FAX_DETECT, AST_OPTION_OPRMODE, AST_OPTION_RELAXDTMF, AST_OPTION_RXGAIN, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, AST_OPTION_TXGAIN, ast_tdd_gen_ecdisa(), buf, dahdi_pvt::channel, dahdi_dtmf_detect_disable(), dahdi_dtmf_detect_enable(), dahdi_ec_disable(), dahdi_ec_enable(), dahdi_get_index, dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::law, len(), LOG_NOTICE, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, oprmode::peer, READ_SIZE, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), dahdi_pvt::sig, dahdi_pvt::sig_pvt, SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), dahdi_pvt::txdrc, dahdi_pvt::txgain, type, and ast_channel_tech::type.

◆ dahdi_show_channel()

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

Definition at line 16150 of file chan_dahdi.c.

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

References a, sig_pri_chan::allocated, ast_channel_name(), ast_cli(), ast_copy_string(), ast_log, ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::busy_cadence, dahdi_pvt::busycount, dahdi_pvt::busydetect, sig_pri_chan::call, dahdi_pvt::callwaitcas, dahdi_pvt::channel, sig_pri_chan::channel, sig_ss7_chan::cic, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_ton, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_pvt::confno, dahdi_pvt::context, dahdi_dnd(), dahdi_pvt::description, dahdi_pvt::destroy, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, dahdi_pvt::head, dahdi_pvt::hwrxgain, dahdi_pvt::hwrxgain_enabled, dahdi_pvt::hwtxgain, dahdi_pvt::hwtxgain_enabled, iflist, iflock, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pvt::law_default, ast_dsp_busy_pattern::length, dahdi_subchannel::linear, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::master, MAX_SLAVES, ast_variable::name, dahdi_pvt::next, ast_variable::next, NULL, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::params, ast_dsp_busy_pattern::pattern, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::radio, sig_pri_chan::resetting, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, S_OR, dahdi_pvt::sig, sig2str, SIG_PRI_RESET_IDLE, dahdi_pvt::sig_pvt, dahdi_pvt::slaves, dahdi_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, dahdi_pvt::tdd, dahdi_pvt::txdrc, dahdi_pvt::txgain, ast_cli_entry::usage, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

◆ dahdi_show_channels()

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

Definition at line 16069 of file chan_dahdi.c.

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

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

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

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

16486{
16487 int pseudo_fd = -1;
16488 struct dahdi_versioninfo vi;
16489
16490 switch (cmd) {
16491 case CLI_INIT:
16492 e->command = "dahdi show version";
16493 e->usage =
16494 "Usage: dahdi show version\n"
16495 " Shows the DAHDI version in use\n";
16496 return NULL;
16497 case CLI_GENERATE:
16498 return NULL;
16499 }
16500 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
16501 ast_cli(a->fd, "Failed to open control file to get version.\n");
16502 return CLI_SUCCESS;
16503 }
16504
16505 strcpy(vi.version, "Unknown");
16506 strcpy(vi.echo_canceller, "Unknown");
16507
16508 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
16509 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
16510 else
16511 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16512
16513 close(pseudo_fd);
16514
16515 return CLI_SUCCESS;
16516}

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

◆ dahdi_sig2str()

static char * dahdi_sig2str ( int  sig)
static

Definition at line 4721 of file chan_dahdi.c.

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

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

15894{
15895 struct dahdi_pvt *p;
15896retry:
15898 for (p = iflist; p; p = p->next) {
15899 ast_mutex_lock(&p->lock);
15900 if (p->owner && !p->restartpending) {
15901 if (ast_channel_trylock(p->owner)) {
15902 if (DEBUG_ATLEAST(3))
15903 ast_verbose("Avoiding deadlock\n");
15904 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15907 goto retry;
15908 }
15909 if (DEBUG_ATLEAST(3))
15910 ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15912 p->restartpending = 1;
15915 }
15917 }
15919}
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2487
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
#define DEBUG_ATLEAST(level)

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

Referenced by dahdi_restart().

◆ dahdi_train_ec()

static void dahdi_train_ec ( struct dahdi_pvt p)
static

Definition at line 5023 of file chan_dahdi.c.

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

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

Referenced by dahdi_handle_event(), and my_train_echocanceller().

◆ dahdi_wait_event()

static int dahdi_wait_event ( int  fd)
inlinestatic

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 852 of file chan_dahdi.c.

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

Referenced by analog_ss_thread(), and my_wait_event().

◆ dahdi_wink()

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

Definition at line 9869 of file chan_dahdi.c.

9870{
9871 int j;
9872 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
9873 for (;;)
9874 {
9875 /* set bits of interest */
9876 j = DAHDI_IOMUX_SIGEVENT;
9877 /* wait for some happening */
9878 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
9879 /* exit loop if we have it */
9880 if (j & DAHDI_IOMUX_SIGEVENT) break;
9881 }
9882 /* get the event info */
9883 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
9884 return 0;
9885}

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

Referenced by analog_ss_thread(), and my_wink().

◆ dahdi_write()

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

Definition at line 9341 of file chan_dahdi.c.

9342{
9343 struct dahdi_pvt *p;
9344 int res;
9345 int idx;
9346
9347 /* Write a frame of (presumably voice) data */
9348 if (frame->frametype != AST_FRAME_VOICE) {
9349 if (frame->frametype != AST_FRAME_IMAGE) {
9350 ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n",
9351 frame->frametype);
9352 }
9353 return 0;
9354 }
9355
9356 /* Return if it's not valid data */
9357 if (!frame->data.ptr || !frame->datalen) {
9358 return 0;
9359 }
9360
9361 p = ast_channel_tech_pvt(ast);
9362 ast_mutex_lock(&p->lock);
9363
9364 idx = dahdi_get_index(ast, p, 0);
9365 if (idx < 0) {
9367 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
9368 return -1;
9369 }
9370
9371 if (p->dialing) {
9373 ast_debug(5, "Dropping frame since I'm still dialing on %s...\n",
9374 ast_channel_name(ast));
9375 return 0;
9376 }
9377 if (!p->owner) {
9379 ast_debug(5, "Dropping frame since there is no active owner on %s...\n",
9380 ast_channel_name(ast));
9381 return 0;
9382 }
9383 if (p->cidspill) {
9385 ast_debug(5, "Dropping frame since I've still got a callerid spill on %s...\n",
9386 ast_channel_name(ast));
9387 return 0;
9388 }
9389
9391 if (!p->subs[idx].linear) {
9392 p->subs[idx].linear = 1;
9393 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9394 if (res)
9395 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
9396 }
9397 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
9400 /* x-law already */
9401 if (p->subs[idx].linear) {
9402 p->subs[idx].linear = 0;
9403 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9404 if (res)
9405 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
9406 }
9407 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
9408 } else {
9410 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n",
9412 return -1;
9413 }
9415 if (res < 0) {
9416 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
9417 return -1;
9418 }
9419 return 0;
9420}
static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
Definition: chan_dahdi.c:9319
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
@ AST_FRAME_IMAGE

References ast_channel_name(), ast_channel_tech_pvt(), ast_debug, ast_format_alaw, ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_get_name(), ast_format_slin, ast_format_ulaw, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log, ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, dahdi_pvt::cidspill, dahdi_get_index, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialing, errno, ast_frame_subclass::format, ast_frame::frametype, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_WARNING, my_dahdi_write(), dahdi_pvt::owner, ast_frame::ptr, ast_frame::subclass, and dahdi_pvt::subs.

◆ dahdichannel_to_ami()

static struct ast_manager_event_blob * dahdichannel_to_ami ( struct stasis_message msg)
static

Definition at line 1980 of file chan_dahdi.c.

1981{
1982 RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
1983 struct ast_channel_blob *obj = stasis_message_data(msg);
1984 struct ast_json *group, *span, *channel;
1985
1986 channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1987 if (!channel_string) {
1988 return NULL;
1989 }
1990
1991 group = ast_json_object_get(obj->blob, "group");
1992 span = ast_json_object_get(obj->blob, "span");
1993 channel = ast_json_object_get(obj->blob, "channel");
1994
1995 return ast_manager_event_blob_create(EVENT_FLAG_CALL, "DAHDIChannel",
1996 "%s"
1997 "DAHDIGroup: %llu\r\n"
1998 "DAHDISpan: %u\r\n"
1999 "DAHDIChannel: %s\r\n",
2000 ast_str_buffer(channel_string),
2002 (unsigned int)ast_json_integer_get(span),
2003 ast_json_string_get(channel));
2004}
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition: json.c:332
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Definition: manager.c:10237
#define EVENT_FLAG_CALL
Definition: manager.h:76
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
Blob of data associated with a channel.
struct ast_channel_snapshot * snapshot
struct ast_json * blob
Abstract JSON element (object, array, string, int, ...).

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

◆ dahdievent_to_analogevent()

static enum analog_event dahdievent_to_analogevent ( int  event)
static

Definition at line 2676 of file chan_dahdi.c.

2677{
2678 enum analog_event res;
2679
2680 switch (event) {
2681 case DAHDI_EVENT_ONHOOK:
2682 res = ANALOG_EVENT_ONHOOK;
2683 break;
2684 case DAHDI_EVENT_RINGOFFHOOK:
2686 break;
2687 case DAHDI_EVENT_WINKFLASH:
2689 break;
2690 case DAHDI_EVENT_ALARM:
2691 res = ANALOG_EVENT_ALARM;
2692 break;
2693 case DAHDI_EVENT_NOALARM:
2695 break;
2696 case DAHDI_EVENT_DIALCOMPLETE:
2698 break;
2699 case DAHDI_EVENT_RINGERON:
2701 break;
2702 case DAHDI_EVENT_RINGEROFF:
2704 break;
2705 case DAHDI_EVENT_HOOKCOMPLETE:
2707 break;
2708 case DAHDI_EVENT_PULSE_START:
2710 break;
2711 case DAHDI_EVENT_POLARITY:
2713 break;
2714 case DAHDI_EVENT_RINGBEGIN:
2716 break;
2717 case DAHDI_EVENT_EC_DISABLED:
2719 break;
2720 case DAHDI_EVENT_REMOVED:
2722 break;
2723 case DAHDI_EVENT_NEONMWI_ACTIVE:
2725 break;
2726 case DAHDI_EVENT_NEONMWI_INACTIVE:
2728 break;
2729#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
2730 case DAHDI_EVENT_TX_CED_DETECTED:
2732 break;
2733 case DAHDI_EVENT_RX_CED_DETECTED:
2735 break;
2736 case DAHDI_EVENT_EC_NLP_DISABLED:
2738 break;
2739 case DAHDI_EVENT_EC_NLP_ENABLED:
2741 break;
2742#endif
2743 case DAHDI_EVENT_PULSEDIGIT:
2745 break;
2746 case DAHDI_EVENT_DTMFDOWN:
2748 break;
2749 case DAHDI_EVENT_DTMFUP:
2750 res = ANALOG_EVENT_DTMFUP;
2751 break;
2752 default:
2753 switch(event & 0xFFFF0000) {
2754 case DAHDI_EVENT_PULSEDIGIT:
2755 case DAHDI_EVENT_DTMFDOWN:
2756 case DAHDI_EVENT_DTMFUP:
2757 /* The event includes a digit number in the low word.
2758 * Converting it to a 'enum analog_event' would remove
2759 * that information. Thus it is returned as-is.
2760 */
2761 return event;
2762 }
2763
2764 res = ANALOG_EVENT_ERROR;
2765 break;
2766 }
2767
2768 return res;
2769}
analog_event
Definition: sig_analog.h:79
@ ANALOG_EVENT_HOOKCOMPLETE
Definition: sig_analog.h:89
@ ANALOG_EVENT_DTMFDOWN
Definition: sig_analog.h:104
@ ANALOG_EVENT_RINGEROFF
Definition: sig_analog.h:88
@ ANALOG_EVENT_PULSE_START
Definition: sig_analog.h:90
@ ANALOG_EVENT_TX_CED_DETECTED
Definition: sig_analog.h:97
@ ANALOG_EVENT_NEONMWI_ACTIVE
Definition: sig_analog.h:95
@ ANALOG_EVENT_RINGBEGIN
Definition: sig_analog.h:92
@ ANALOG_EVENT_ONHOOK
Definition: sig_analog.h:81
@ ANALOG_EVENT_EC_DISABLED
Definition: sig_analog.h:93
@ ANALOG_EVENT_WINKFLASH
Definition: sig_analog.h:83
@ ANALOG_EVENT_ERROR
Definition: sig_analog.h:101
@ ANALOG_EVENT_PULSEDIGIT
Definition: sig_analog.h:103
@ ANALOG_EVENT_RINGERON
Definition: sig_analog.h:87
@ ANALOG_EVENT_RX_CED_DETECTED
Definition: sig_analog.h:98
@ ANALOG_EVENT_ALARM
Definition: sig_analog.h:84
@ ANALOG_EVENT_DIALCOMPLETE
Definition: sig_analog.h:86
@ ANALOG_EVENT_EC_NLP_ENABLED
Definition: sig_analog.h:100
@ ANALOG_EVENT_POLARITY
Definition: sig_analog.h:91
@ ANALOG_EVENT_NEONMWI_INACTIVE
Definition: sig_analog.h:96
@ ANALOG_EVENT_DTMFUP
Definition: sig_analog.h:105
@ ANALOG_EVENT_EC_NLP_DISABLED
Definition: sig_analog.h:99
@ ANALOG_EVENT_RINGOFFHOOK
Definition: sig_analog.h:82
@ ANALOG_EVENT_REMOVED
Definition: sig_analog.h:94
@ ANALOG_EVENT_NOALARM
Definition: sig_analog.h:85
Definition: astman.c:222

References ANALOG_EVENT_ALARM, ANALOG_EVENT_DIALCOMPLETE, ANALOG_EVENT_DTMFDOWN, ANALOG_EVENT_DTMFUP, ANALOG_EVENT_EC_DISABLED, ANALOG_EVENT_EC_NLP_DISABLED, ANALOG_EVENT_EC_NLP_ENABLED, ANALOG_EVENT_ERROR, ANALOG_EVENT_HOOKCOMPLETE, ANALOG_EVENT_NEONMWI_ACTIVE, ANALOG_EVENT_NEONMWI_INACTIVE, ANALOG_EVENT_NOALARM, ANALOG_EVENT_ONHOOK, ANALOG_EVENT_POLARITY, ANALOG_EVENT_PULSE_START, ANALOG_EVENT_PULSEDIGIT, ANALOG_EVENT_REMOVED, ANALOG_EVENT_RINGBEGIN, ANALOG_EVENT_RINGEROFF, ANALOG_EVENT_RINGERON, ANALOG_EVENT_RINGOFFHOOK, ANALOG_EVENT_RX_CED_DETECTED, ANALOG_EVENT_TX_CED_DETECTED, and ANALOG_EVENT_WINKFLASH.

Referenced by do_monitor(), my_get_callerid(), and my_get_event().

◆ dahdisig_to_analogsig()

static enum analog_sigtype dahdisig_to_analogsig ( int  sig)
static

Definition at line 1252 of file chan_dahdi.c.

1253{
1254 switch (sig) {
1255 case SIG_FXOLS:
1256 return ANALOG_SIG_FXOLS;
1257 case SIG_FXOGS:
1258 return ANALOG_SIG_FXOGS;
1259 case SIG_FXOKS:
1260 return ANALOG_SIG_FXOKS;
1261 case SIG_FXSLS:
1262 return ANALOG_SIG_FXSLS;
1263 case SIG_FXSGS:
1264 return ANALOG_SIG_FXSGS;
1265 case SIG_FXSKS:
1266 return ANALOG_SIG_FXSKS;
1267 case SIG_EMWINK:
1268 return ANALOG_SIG_EMWINK;
1269 case SIG_EM:
1270 return ANALOG_SIG_EM;
1271 case SIG_EM_E1:
1272 return ANALOG_SIG_EM_E1;
1273 case SIG_FEATD:
1274 return ANALOG_SIG_FEATD;
1275 case SIG_FEATDMF:
1276 return ANALOG_SIG_FEATDMF;
1277 case SIG_E911:
1278 return SIG_E911;
1279 case SIG_FGC_CAMA:
1280 return ANALOG_SIG_FGC_CAMA;
1281 case SIG_FGC_CAMAMF:
1282 return ANALOG_SIG_FGC_CAMAMF;
1283 case SIG_FEATB:
1284 return ANALOG_SIG_FEATB;
1285 case SIG_SFWINK:
1286 return ANALOG_SIG_SFWINK;
1287 case SIG_SF:
1288 return ANALOG_SIG_SF;
1289 case SIG_SF_FEATD:
1290 return ANALOG_SIG_SF_FEATD;
1291 case SIG_SF_FEATDMF:
1292 return ANALOG_SIG_SF_FEATDMF;
1293 case SIG_FEATDMF_TA:
1294 return ANALOG_SIG_FEATDMF_TA;
1295 case SIG_SF_FEATB:
1296 return ANALOG_SIG_FEATB;
1297 default:
1298 return -1;
1299 }
1300}
@ ANALOG_SIG_FEATD
Definition: sig_analog.h:56
@ ANALOG_SIG_FEATDMF_TA
Definition: sig_analog.h:66
@ ANALOG_SIG_FGC_CAMAMF
Definition: sig_analog.h:60
@ ANALOG_SIG_FXOLS
Definition: sig_analog.h:47
@ ANALOG_SIG_FEATDMF
Definition: sig_analog.h:57
@ ANALOG_SIG_EM_E1
Definition: sig_analog.h:55
@ ANALOG_SIG_EMWINK
Definition: sig_analog.h:53
@ ANALOG_SIG_FXOKS
Definition: sig_analog.h:48
@ ANALOG_SIG_SF
Definition: sig_analog.h:63
@ ANALOG_SIG_FGC_CAMA
Definition: sig_analog.h:59
@ ANALOG_SIG_FXSLS
Definition: sig_analog.h:50
@ ANALOG_SIG_EM
Definition: sig_analog.h:54
@ ANALOG_SIG_FXOGS
Definition: sig_analog.h:49
@ ANALOG_SIG_FXSGS
Definition: sig_analog.h:52
@ ANALOG_SIG_SF_FEATDMF
Definition: sig_analog.h:65
@ ANALOG_SIG_SFWINK
Definition: sig_analog.h:62
@ ANALOG_SIG_FEATB
Definition: sig_analog.h:61
@ ANALOG_SIG_SF_FEATD
Definition: sig_analog.h:64
@ ANALOG_SIG_FXSKS
Definition: sig_analog.h:51

References ANALOG_SIG_EM, ANALOG_SIG_EM_E1, ANALOG_SIG_EMWINK, ANALOG_SIG_FEATB, ANALOG_SIG_FEATD, ANALOG_SIG_FEATDMF, ANALOG_SIG_FEATDMF_TA, ANALOG_SIG_FGC_CAMA, ANALOG_SIG_FGC_CAMAMF, ANALOG_SIG_FXOGS, ANALOG_SIG_FXOKS, ANALOG_SIG_FXOLS, ANALOG_SIG_FXSGS, ANALOG_SIG_FXSKS, ANALOG_SIG_FXSLS, ANALOG_SIG_SF, ANALOG_SIG_SF_FEATD, ANALOG_SIG_SF_FEATDMF, ANALOG_SIG_SFWINK, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.

Referenced by mkintf().

◆ deep_copy_dahdi_chan_conf()

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

Definition at line 20016 of file chan_dahdi.c.

20017{
20018 struct ast_cc_config_params *cc_params;
20019
20020 cc_params = dest->chan.cc_params;
20021 *dest = *src;
20022 dest->chan.cc_params = cc_params;
20024}

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

Referenced by setup_dahdi_int().

◆ destroy_all_channels()

static void destroy_all_channels ( void  )
static

Definition at line 5995 of file chan_dahdi.c.

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

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

Referenced by __unload_module(), and dahdi_restart().

◆ destroy_channel()

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

Definition at line 5977 of file chan_dahdi.c.

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

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

Referenced by dahdi_destroy_channel_range(), and dahdi_hangup().

◆ destroy_dahdi_pvt()

static void destroy_dahdi_pvt ( struct dahdi_pvt pvt)
static

Definition at line 5897 of file chan_dahdi.c.

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

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

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

References args, ARRAY_LEN, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log, AST_NONSTANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), dahdi_starting_point::backwards, dahdi_starting_point::cadence, CHAN_PSEUDO, dahdi_starting_point::channelmatch, errno, dahdi_starting_point::groupmatch, ifend, iflist, LOG_ERROR, LOG_WARNING, dahdi_pvt::next, NULL, dahdi_starting_point::opt, PATH_MAX, dahdi_pvt::prev, round_robin, dahdi_starting_point::roundrobin, dahdi_starting_point::rr_starting_point, and dahdi_starting_point::span.

Referenced by dahdi_cc_callback(), and dahdi_request().

◆ digit_to_dtmfindex()

static int digit_to_dtmfindex ( char  digit)
static

Definition at line 4551 of file chan_dahdi.c.

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

References digit.

Referenced by dahdi_digit_begin().

◆ do_monitor()

static void * do_monitor ( void *  data)
static

Definition at line 11932 of file chan_dahdi.c.

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

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

Referenced by restart_monitor().

◆ drc_sample()

static int drc_sample ( int  sample,
float  drc 
)
static

Definition at line 5068 of file chan_dahdi.c.

5069{
5070 float neg;
5071 float shallow, steep;
5072 float max = SHRT_MAX;
5073
5074 neg = (sample < 0 ? -1 : 1);
5075 steep = drc*sample;
5076 shallow = neg*(max-max/drc)+(float)sample/drc;
5077 if (fabsf(steep) < fabsf(shallow)) {
5078 sample = steep;
5079 }
5080 else {
5081 sample = shallow;
5082 }
5083
5084 return sample;
5085}
#define max(a, b)
Definition: f2c.h:198

References max.

Referenced by fill_rxgain(), and fill_txgain().

◆ duplicate_pseudo()

static struct dahdi_pvt * duplicate_pseudo ( struct dahdi_pvt src)
static

Definition at line 13758 of file chan_dahdi.c.

13759{
13760 struct dahdi_pvt *p;
13761 struct dahdi_bufferinfo bi;
13762 int res;
13763
13764 p = ast_malloc(sizeof(*p));
13765 if (!p) {
13766 return NULL;
13767 }
13768 *p = *src;
13769
13770 /* Must deep copy the cc_params. */
13772 if (!p->cc_params) {
13773 ast_free(p);
13774 return NULL;
13775 }
13777
13779 p->next = NULL;
13780 p->prev = NULL;
13781 ast_mutex_init(&p->lock);
13782 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13783 if (p->subs[SUB_REAL].dfd < 0) {
13784 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13786 return NULL;
13787 }
13788 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13789 if (!res) {
13790 bi.txbufpolicy = src->buf_policy;
13791 bi.rxbufpolicy = src->buf_policy;
13792 bi.numbufs = src->buf_no;
13793 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13794 if (res < 0) {
13795 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13796 }
13797 } else
13798 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13799 p->destroy = 1;
13801 return p;
13802}
static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5622
#define ast_mutex_init(pmutex)
Definition: lock.h:190

References ast_cc_config_params_init, ast_cc_copy_config_params(), ast_free, ast_log, ast_malloc, ast_mutex_init, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::cc_params, dahdi_iflist_insert(), DAHDI_IFLIST_NONE, dahdi_open(), dahdi_pvt::destroy, destroy_dahdi_pvt(), dahdi_subchannel::dfd, errno, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, dahdi_pvt::next, NULL, dahdi_pvt::prev, SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::which_iflist.

Referenced by dahdi_request().

◆ event2str()

static const char * event2str ( int  event)
static

Definition at line 4712 of file chan_dahdi.c.

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

References ARRAY_LEN, buf, and events.

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

◆ fill_rxgain()

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

Definition at line 5138 of file chan_dahdi.c.

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

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

Referenced by set_actual_rxgain().

◆ fill_txgain()

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

Definition at line 5088 of file chan_dahdi.c.

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

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

Referenced by set_actual_txgain().

◆ find_channel()

static struct dahdi_pvt * find_channel ( int  channel)
static

Definition at line 16835 of file chan_dahdi.c.

16836{
16837 struct dahdi_pvt *p;
16838
16840 for (p = iflist; p; p = p->next) {
16841 if (p->channel == channel) {
16842 break;
16843 }
16844 }
16846 return p;
16847}

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

Referenced by find_channel_from_str().

◆ find_channel_from_str()

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

Definition at line 16858 of file chan_dahdi.c.

16859{
16860 int chan_num;
16861
16862 if (sscanf(channel, "%30d", &chan_num) != 1) {
16863 /* Not numeric string. */
16864 return NULL;
16865 }
16866
16867 return find_channel(chan_num);
16868}
static struct dahdi_pvt * find_channel(int channel)
Definition: chan_dahdi.c:16835

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

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

◆ find_next_iface_in_span()

static struct dahdi_pvt * find_next_iface_in_span ( struct dahdi_pvt cur)
static

Definition at line 5886 of file chan_dahdi.c.

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

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

Referenced by destroy_dahdi_pvt().

◆ fxo_pvt()

static struct dahdi_pvt * fxo_pvt ( struct ast_channel chan)
static

Return DAHDI pivot if channel is FXO signalled.

Definition at line 2912 of file chan_dahdi.c.

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

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

Referenced by polarity_read(), and polarity_write().

◆ gen_pvt_field_callback() [1/3]

gen_pvt_field_callback ( int  ,
firstdigit_timeout   
)

◆ gen_pvt_field_callback() [2/3]

gen_pvt_field_callback ( int  ,
interdigit_timeout   
)

◆ gen_pvt_field_callback() [3/3]

gen_pvt_field_callback ( int  ,
matchdigit_timeout   
)

◆ get_alarms()

static int get_alarms ( struct dahdi_pvt p)
static

Checks channel for alarms

Parameters
pa channel to check for alarms.
Returns
the alarms on the span to which the channel belongs, or alarms on the channel if no span alarms.

Definition at line 7637 of file chan_dahdi.c.

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

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

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

◆ handle_alarms()

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

Definition at line 7797 of file chan_dahdi.c.

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

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

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

◆ handle_clear_alarms()

static void handle_clear_alarms ( struct dahdi_pvt p)
static

Definition at line 3866 of file chan_dahdi.c.

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

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

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

◆ handle_dahdi_show_cadences()

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

Definition at line 16353 of file chan_dahdi.c.

16354{
16355 int i, j;
16356 switch (cmd) {
16357 case CLI_INIT:
16358 e->command = "dahdi show cadences";
16359 e->usage =
16360 "Usage: dahdi show cadences\n"
16361 " Shows all cadences currently defined\n";
16362 return NULL;
16363 case CLI_GENERATE:
16364 return NULL;
16365 }
16366 for (i = 0; i < num_cadence; i++) {
16367 char output[1024];
16368 char tmp[16], tmp2[64];
16369 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
16370 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
16371
16372 for (j = 0; j < 16; j++) {
16373 if (cadences[i].ringcadence[j] == 0)
16374 break;
16375 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
16376 if (cidrings[i] * 2 - 1 == j)
16377 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
16378 else
16379 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
16380 if (j != 0)
16381 strncat(output, ",", sizeof(output) - strlen(output) - 1);
16382 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
16383 }
16384 ast_cli(a->fd,"%s\n",output);
16385 }
16386 return CLI_SUCCESS;
16387}
static int cidrings[NUM_CADENCE_MAX]
cidrings says in which pause to transmit the cid information, where the first pause is 1,...
Definition: chan_dahdi.c:771
static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
Definition: chan_dahdi.c:760
static int num_cadence
Definition: chan_dahdi.c:755
#define COLOR_MAGENTA
Definition: term.h:60
#define COLOR_BLACK
Definition: term.h:50
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:235
#define COLOR_GREEN
Definition: term.h:54

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

◆ handle_init_event()

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

Definition at line 11668 of file chan_dahdi.c.

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

References analog_ss_thread(), ast_callid_threadstorage_auto(), ast_callid_threadstorage_auto_clean(), ast_free, ast_hangup(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_detached, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verb, ast_channel::callid, dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::cidspill, dahdi_ec_disable(), dahdi_ec_enable(), dahdi_new(), dahdi_set_hook(), dahdi_subchannel::dfd, errno, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_neon, notify_message(), NULL, dahdi_pvt::polarity, POLARITY_REV, dahdi_pvt::radio, restore_conference(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, sig_pri_chan_alarm_notify(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sig_ss7_set_alarm(), SUB_REAL, and dahdi_pvt::subs.

Referenced by do_monitor().

◆ has_voicemail()

static int has_voicemail ( struct dahdi_pvt p)
static

Definition at line 5363 of file chan_dahdi.c.

5364{
5365 int new_msgs;
5366 RAII_VAR(struct stasis_message *, mwi_message, NULL, ao2_cleanup);
5367
5368 /* A manual MWI disposition has been requested, use that instead
5369 * if this is for sending the new MWI indication. */
5370 if (p->mwioverride_active) {
5371 /* We don't clear p->mwioverride_active automatically,
5372 * because otherwise do_monitor would just change it back to the way it was.
5373 * We need to keep the override active until explicitly disabled by the user,
5374 * so that we can keep returning the correct answer in subsequent calls to do_monitor. */
5375 ast_debug(6, "MWI manual override active on channel %d: pretending that it should be %s\n",
5376 p->channel, p->mwioverride_disposition ? "active" : "inactive");
5377 return p->mwioverride_disposition;
5378 }
5379
5381 if (mwi_message) {
5382 struct ast_mwi_state *mwi_state = stasis_message_data(mwi_message);
5383 new_msgs = mwi_state->new_msgs;
5384 } else {
5386 }
5387
5388 return new_msgs;
5389}
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX"....
Definition: main/app.c:582
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
struct stasis_cache * ast_mwi_state_cache(void)
Backend cache for ast_mwi_topic_cached().
Definition: mwi.c:94
struct stasis_message * stasis_cache_get(struct stasis_cache *cache, struct stasis_message_type *type, const char *id)
Retrieve an item from the cache for the ast_eid_default entity.
Definition: stasis_cache.c:686
The structure that contains MWI state.
Definition: mwi.h:455
int new_msgs
Definition: mwi.h:459

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

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

◆ is_group_or_channel_match()

static int is_group_or_channel_match ( struct dahdi_pvt p,
int  span,
ast_group_t  groupmatch,
int *  groupmatched,
int  channelmatch,
int *  channelmatched 
)
static

Definition at line 13519 of file chan_dahdi.c.

13520{
13521#if defined(HAVE_PRI)
13522 if (0 < span) {
13523 /* The channel must be on the specified PRI span. */
13524 if (!p->pri || p->pri->span != span) {
13525 return 0;
13526 }
13527 if (!groupmatch && channelmatch == -1) {
13528 /* Match any group since it only needs to be on the PRI span. */
13529 *groupmatched = 1;
13530 return 1;
13531 }
13532 }
13533#endif /* defined(HAVE_PRI) */
13534 /* check group matching */
13535 if (groupmatch) {
13536 if ((p->group & groupmatch) != groupmatch)
13537 /* Doesn't match the specified group, try the next one */
13538 return 0;
13539 *groupmatched = 1;
13540 }
13541 /* Check to see if we have a channel match */
13542 if (channelmatch != -1) {
13543 if (p->channel != channelmatch)
13544 /* Doesn't match the specified channel, try the next one */
13545 return 0;
13546 *channelmatched = 1;
13547 }
13548
13549 return 1;
13550}

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

Referenced by dahdi_cc_callback(), and dahdi_request().

◆ isourconf()

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

Definition at line 4825 of file chan_dahdi.c.

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

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

Referenced by conf_del().

◆ isslavenative()

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

Definition at line 4855 of file chan_dahdi.c.

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

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

Referenced by dahdi_conf_update(), and my_complete_conference_update().

◆ load_module()

static int load_module ( void  )
static

Load the module.

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

Definition at line 20361 of file chan_dahdi.c.

20362{
20363 int res;
20364#if defined(HAVE_PRI) || defined(HAVE_SS7)
20365 int y;
20366#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
20367
20368 if (STASIS_MESSAGE_TYPE_INIT(dahdichannel_type)) {
20370 }
20371
20374 }
20378
20382 }
20383
20384#ifdef HAVE_PRI
20385 memset(pris, 0, sizeof(pris));
20386 for (y = 0; y < NUM_SPANS; y++) {
20387 sig_pri_init_pri(&pris[y].pri);
20388 }
20389 pri_set_error(dahdi_pri_error);
20390 pri_set_message(dahdi_pri_message);
20391 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
20392#ifdef HAVE_PRI_PROG_W_CAUSE
20393 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
20394#endif
20395#if defined(HAVE_PRI_CCSS)
20396 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
20397 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
20400 }
20401#endif /* defined(HAVE_PRI_CCSS) */
20402 if (sig_pri_load(
20403#if defined(HAVE_PRI_CCSS)
20404 dahdi_pri_cc_type
20405#else
20406 NULL
20407#endif /* defined(HAVE_PRI_CCSS) */
20408 )) {
20411 }
20412#endif
20413#if defined(HAVE_SS7)
20414 memset(linksets, 0, sizeof(linksets));
20415 for (y = 0; y < NUM_SPANS; y++) {
20416 sig_ss7_init_linkset(&linksets[y].ss7);
20417 }
20418 ss7_set_error(dahdi_ss7_error);
20419 ss7_set_message(dahdi_ss7_message);
20420 ss7_set_hangup(sig_ss7_cb_hangup);
20421 ss7_set_notinservice(sig_ss7_cb_notinservice);
20422 ss7_set_call_null(sig_ss7_cb_call_null);
20423#endif /* defined(HAVE_SS7) */
20424 res = setup_dahdi(0);
20425 /* Make sure we can register our DAHDI channel type */
20426 if (res) {
20429 }
20431 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
20434 }
20435#ifdef HAVE_PRI
20436 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
20437#endif
20438#if defined(HAVE_SS7)
20439 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
20440#endif /* defined(HAVE_SS7) */
20441#ifdef HAVE_OPENR2
20442 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
20443 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
20444#endif
20445
20447
20449 memset(round_robin, 0, sizeof(round_robin));
20450 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
20452 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
20455 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
20456 ast_manager_register_xml("DAHDIShowStatus", 0, action_dahdishowstatus);
20458#if defined(HAVE_PRI)
20459 ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
20460 ast_manager_register_xml("PRIDebugSet", 0, action_pri_debug_set);
20461 ast_manager_register_xml("PRIDebugFileSet", EVENT_FLAG_SYSTEM, action_pri_debug_file_set);
20462 ast_manager_register_xml("PRIDebugFileUnset", 0, action_pri_debug_file_unset);
20463#endif /* defined(HAVE_PRI) */
20464
20466
20467 return res;
20468}
int dahdi_native_load(const struct ast_channel_tech *tech)
int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks)
Register a set of monitor callbacks with the core.
Definition: ccss.c:1168
int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
Register a set of agent callbacks with the core.
Definition: ccss.c:1223
static int __unload_module(void)
Definition: chan_dahdi.c:18188
static int action_transfer(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16908
static int action_dahdidndon(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16870
static int action_dahdishowchannels(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16986
static int action_dahdirestart(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16059
static int action_dahdidndoff(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16889
static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16954
static int action_transferhangup(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16931
static int action_dahdishowstatus(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:17074
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:539
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define ast_cond_init(cond, attr)
Definition: lock.h:205
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:192
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1559
int sig_pri_load(const char *cc_type_name)
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493

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

◆ mkintf()

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

< Current channel structure initializing

< TRUE if the channel interface already exists.

Definition at line 12571 of file chan_dahdi.c.

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

References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, ANALOG_CID_START_DTMF_NOALERT, ANALOG_CID_START_POLARITY, ANALOG_CID_START_POLARITY_IN, ANALOG_CID_START_RING, analog_config_complete(), analog_new(), ANALOG_SIG_NONE, dahdi_pvt::ani_info_digits, analog_pvt::ani_info_digits, dahdi_pvt::ani_timeout, analog_pvt::ani_timeout, dahdi_pvt::ani_wink_time, analog_pvt::ani_wink_time, dahdi_pvt::answeronpolarityswitch, analog_pvt::answeronpolarityswitch, ARRAY_LEN, ast_calloc, ast_cc_config_params_init, ast_cc_copy_config_params(), ast_copy_string(), ast_db_del(), ast_db_get(), ast_dsp_set_digitmode(), ast_free, ast_log, ast_mutex_init, ast_mwi_subscribe_pool(), ast_ref_namedgroups(), ast_smdi_interface_find(), ast_strlen_zero(), ast_unref_namedgroups(), ast_variable_list_replace(), ast_variable_new, ast_variables_destroy(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufsize, dahdi_pvt::busy_cadence, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::calledsubscriberheld, analog_pvt::calledsubscriberheld, dahdi_pvt::callgroup, dahdi_pvt::callprogress, dahdi_pvt::callreturn, analog_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, analog_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, analog_pvt::cancallforward, dahdi_pvt::canpark, analog_pvt::canpark, dahdi_pvt::cc_params, CHAN_PSEUDO, dahdi_pvt::channel, analog_pvt::channel, sig_pri_chan::channel, sig_ss7_chan::channel, sig_ss7_chan::cic, dahdi_pvt::cid_name, analog_pvt::cid_name, dahdi_pvt::cid_num, analog_pvt::cid_num, dahdi_pvt::cid_rxgain, CID_SIG_SMDI, dahdi_pvt::cid_signalling, analog_pvt::cid_signalling, dahdi_pvt::cid_start, analog_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_tag, dahdi_pvt::cid_ton, dahdi_pvt::confno, dahdi_pvt::context, sig_pri_chan::context, sig_ss7_chan::context, dahdi_analog_lib_handles(), dahdi_conf_update(), dahdi_iflist_insert(), dahdi_open(), dahdi_set_hook(), dahdi_sig2str(), dahdi_sig_pri_lib_handles(), dahdisig_to_analogsig(), dahdi_pvt::dahditrcallerid, analog_pvt::dahditrcallerid, dahdi_pvt::defcontext, dahdi_pvt::description, dahdi_pvt::destroy, destroy_dahdi_pvt(), dahdi_subchannel::dfd, dahdi_pvt::dialmode, analog_pvt::dialmode, sig_pri_span::dialplan, dahdi_pvt::dialtone_detect, sig_ss7_chan::dpc, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, analog_pvt::echotraining, errno, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxdetect_timeout, ast_variable::file, dahdi_pvt::firstdigit_timeout, dahdi_pvt::firstradio, analog_pvt::fxsoffhookstate, get_alarms(), dahdi_pvt::group, handle_alarms(), dahdi_pvt::hanguponpolarityswitch, analog_pvt::hanguponpolarityswitch, dahdi_pvt::head, dahdi_pvt::hidecallerid, sig_pri_chan::hidecallerid, sig_ss7_chan::hidecallerid, dahdi_pvt::hidecalleridname, sig_pri_chan::hidecalleridname, dahdi_pvt::hwrxgain, dahdi_pvt::hwrxgain_enabled, dahdi_pvt::hwtxgain, dahdi_pvt::hwtxgain_enabled, sig_pri_span::idledial, sig_pri_span::idleext, ifcount, iflist, dahdi_pvt::immediate, analog_pvt::immediate, sig_pri_chan::immediate, sig_ss7_chan::immediate, dahdi_pvt::immediatering, analog_pvt::immediatering, dahdi_pvt::inalarm, analog_pvt::inalarm, sig_pri_chan::inalarm, sig_ss7_chan::inalarm, dahdi_pvt::inservice, sig_ss7_chan::inservice, dahdi_pvt::interdigit_timeout, dahdi_pvt::language, dahdi_pvt::lastnumredial, analog_pvt::lastnumredial, dahdi_pvt::law, dahdi_pvt::law_default, LINKSET_FLAG_INITIALHWBLO, dahdi_pvt::locallyblocked, sig_ss7_chan::locallyblocked, dahdi_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::matchdigit_timeout, sig_pri_span::minidle, sig_pri_span::minunused, dahdi_pvt::mohinterpret, sig_pri_chan::mohinterpret, sig_ss7_chan::mohinterpret, dahdi_pvt::mohsuggest, analog_pvt::mohsuggest, analog_pvt::msgstate, dahdi_pvt::mwi_event_sub, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, ast_variable::name, dahdi_pvt::named_callgroups, dahdi_pvt::named_pickupgroups, dahdi_pvt::next, ast_variable::next, sig_pri_span::nodetype, NULL, NUM_SPANS, sig_pri_span::numchans, analog_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_pvt::outsigmod, analog_pvt::outsigmod, dahdi_pvt::parkinglot, dahdi_pvt::permcallwaiting, analog_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, analog_pvt::permhidecallerid, dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, analog_pvt::polarityonanswerdelay, dahdi_pvt::priexclusive, sig_pri_chan::priexclusive, dahdi_pvt::priindication_oob, sig_pri_chan::priindication_oob, dahdi_pvt::propconfno, dahdi_pvt::pulse, analog_pvt::pulse, sig_pri_span::pvts, dahdi_pvt::radio, distRingData::range, dahdi_pvt::remotelyblocked, sig_ss7_chan::remotelyblocked, dahdi_pvt::reoriginate, dahdi_pvt::restrictcid, dahdi_distRings::ringnum, analog_pvt::ringt, ringt_base, dahdi_pvt::ringt_base, analog_pvt::ringt_base, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, set_actual_gain(), set_hwgain(), dahdi_pvt::sig, sig2str, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, sig_pri_chan_new(), SIG_PRI_LIB_HANDLE_CASES, SIG_PRI_NUM_DCHANS, sig_pri_set_alarm(), dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sig_ss7_chan_new(), sig_ss7_set_alarm(), sigtype_to_signalling(), dahdi_pvt::smdi_iface, analog_pvt::smdi_iface, dahdi_pvt::span, SS7_BLOCKED_HARDWARE, stasis_subscription_cb_noop(), state, dahdi_pvt::stripmsd, analog_pvt::stripmsd, sig_pri_chan::stripmsd, sig_ss7_chan::stripmsd, SUB_REAL, dahdi_pvt::subs, sig_pri_span::switchtype, dahdi_pvt::threewaycalling, analog_pvt::threewaycalling, dahdi_pvt::threewaysilenthold, dahdi_pvt::tonezone, dahdi_pvt::transfer, analog_pvt::transfer, dahdi_pvt::transfertobusy, analog_pvt::transfertobusy, sig_pri_span::trunkgroup, dahdi_pvt::txdrc, dahdi_pvt::txgain, dahdi_pvt::use_callerid, analog_pvt::use_callerid, sig_pri_chan::use_callerid, sig_ss7_chan::use_callerid, dahdi_pvt::use_callingpres, sig_pri_chan::use_callingpres, sig_ss7_chan::use_callingpres, dahdi_pvt::use_smdi, analog_pvt::use_smdi, usedistinctiveringdetection, dahdi_pvt::usedistinctiveringdetection, analog_pvt::usedistinctiveringdetection, dahdi_pvt::usefaxbuffers, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

Referenced by build_channels(), and process_dahdi().

◆ monitor_pfds_clean()

static void monitor_pfds_clean ( void *  arg)
static

Definition at line 11927 of file chan_dahdi.c.

11927 {
11928 struct pollfd **pfds = arg;
11929 ast_free(*pfds);
11930}

References ast_free.

Referenced by do_monitor().

◆ mwi_send_init()

static int mwi_send_init ( struct dahdi_pvt pvt)
static

Definition at line 11333 of file chan_dahdi.c.

11334{
11335 int x;
11336
11337#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11338 /* Determine how this spill is to be sent */
11339 if (pvt->mwisend_rpas) {
11341 pvt->mwisendactive = 1;
11342 } else if (pvt->mwisend_fsk) {
11344 pvt->mwisendactive = 1;
11345 } else {
11346 pvt->mwisendactive = 0;
11347 return 0;
11348 }
11349#else
11350 if (mwisend_rpas) {
11352 } else {
11354 }
11355 pvt->mwisendactive = 1;
11356#endif
11357
11358 if (pvt->cidspill) {
11359 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11360 ast_free(pvt->cidspill);
11361 pvt->cidspill = NULL;
11362 pvt->cidpos = 0;
11363 pvt->cidlen = 0;
11364 }
11366 if (!pvt->cidspill) {
11367 pvt->mwisendactive = 0;
11368 return -1;
11369 }
11370 x = DAHDI_FLUSH_BOTH;
11371 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11372 x = 3000;
11373 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11374#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11375 if (pvt->mwisend_fsk) {
11376#endif
11378 CID_MWI_TYPE_MDMF_FULL, AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11379 pvt->cidpos = 0;
11380#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11381 }
11382#endif
11383 return 0;
11384}
int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct ast_format *codec, const char *name, const char *number, int flags)
Generate message waiting indicator.
Definition: callerid.c:952
#define MAX_CALLERID_SIZE
Definition: callerid.h:50
#define CID_MWI_TYPE_MDMF_FULL
Definition: callerid.h:83
static int mwisend_rpas
Definition: chan_dahdi.c:793
@ MWI_SEND_SA
Definition: chan_dahdi.h:102
@ MWI_SEND_SPILL
Definition: chan_dahdi.h:105
struct mwisend_info mwisend_data
Definition: chan_dahdi.h:482
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 11386 of file chan_dahdi.c.

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

References AS_RP_cadence, ast_free, ast_log, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), dahdi_subchannel::dfd, errno, LOG_WARNING, MWI_SEND_CLEANUP, MWI_SEND_DONE, MWI_SEND_PAUSE, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_SPILL, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, NULL, mwisend_info::pause, SUB_REAL, and dahdi_pvt::subs.

Referenced by do_monitor().

◆ mwi_send_process_event()

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

Definition at line 11474 of file chan_dahdi.c.

11475{
11476 int handled = 0;
11477
11479 switch (event) {
11480 case DAHDI_EVENT_RINGEROFF:
11482 handled = 1;
11483
11484 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11485 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11486 ast_free(pvt->cidspill);
11487 pvt->cidspill = NULL;
11489 pvt->mwisendactive = 0;
11490 } else {
11492 gettimeofday(&pvt->mwisend_data.pause, NULL);
11493 }
11494 }
11495 break;
11496 /* Going off hook, I need to punt this spill */
11497 case DAHDI_EVENT_RINGOFFHOOK:
11498 if (pvt->cidspill) {
11499 ast_free(pvt->cidspill);
11500 pvt->cidspill = NULL;
11501 pvt->cidpos = 0;
11502 pvt->cidlen = 0;
11503 }
11505 pvt->mwisendactive = 0;
11506 break;
11507 case DAHDI_EVENT_RINGERON:
11508 case DAHDI_EVENT_HOOKCOMPLETE:
11509 break;
11510 default:
11511 break;
11512 }
11513 }
11514 return handled;
11515}

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

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

References analog_ss_thread(), analog_ss_thread_start(), ast_callid_threadstorage_auto(), ast_callid_threadstorage_auto_clean(), ast_free, ast_hangup(), AST_LAW, ast_log, ast_pthread_create_detached, AST_STATE_RING, mwi_thread_data::buf, bump_gains(), calc_energy(), callerid_feed(), callerid_free(), callerid_get(), callerid_new(), ast_channel::callid, dahdi_pvt::channel, CID_MSGWAITING, CID_NOMSGWAITING, dahdi_pvt::cid_signalling, dahdi_analog_lib_handles(), dahdi_get_event(), dahdi_new(), dahdi_subchannel::dfd, errno, event2str(), callerid_state::flags, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::inalarm, analog_pvt::inalarm, mwi_thread_data::len, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, mwilevel, dahdi_pvt::mwimonitoractive, name, notify_message(), NULL, callerid_state::number, dahdi_pvt::oprmode, mwi_thread_data::pvt, dahdi_pvt::radio, restore_gains(), result, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.

Referenced by do_monitor().

◆ my_all_subchannels_hungup()

static void my_all_subchannels_hungup ( void *  pvt)
static

Definition at line 2333 of file chan_dahdi.c.

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

References ast_dsp_free(), ast_log, dahdi_pvt::channel, dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, dahdi_pvt::dsp, errno, dahdi_pvt::faxhandled, dahdi_pvt::law, dahdi_pvt::law_default, LOG_WARNING, NULL, num_restart_pending, dahdi_subchannel::owner, dahdi_pvt::owner, reset_conf(), restart_monitor(), SUB_REAL, and dahdi_pvt::subs.

◆ my_allocate_sub()

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

Definition at line 2650 of file chan_dahdi.c.

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

References alloc_sub(), and analogsub_to_dahdisub().

◆ my_answer_polarityswitch()

static void my_answer_polarityswitch ( void *  pvt)
static

Definition at line 2885 of file chan_dahdi.c.

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

References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().

◆ my_callwait()

static int my_callwait ( void *  pvt)
static

Definition at line 1734 of file chan_dahdi.c.

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

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

◆ my_cancel_cidspill()

static void my_cancel_cidspill ( void *  pvt)
static

Definition at line 2283 of file chan_dahdi.c.

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

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

◆ my_check_confirmanswer()

static int my_check_confirmanswer ( void *  pvt)
static

Definition at line 2266 of file chan_dahdi.c.

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

References dahdi_pvt::confirmanswer.

◆ my_check_for_conference()

static int my_check_for_conference ( void *  pvt)
static

Definition at line 2443 of file chan_dahdi.c.

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

References check_for_conference().

◆ my_check_waitingfordt()

static int my_check_waitingfordt ( void *  pvt)
static

Definition at line 2249 of file chan_dahdi.c.

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

References dahdi_pvt::waitingfordt.

◆ my_complete_conference_update()

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

Definition at line 2393 of file chan_dahdi.c.

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

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

◆ my_conf_add()

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

Definition at line 2383 of file chan_dahdi.c.

2384{
2385 struct dahdi_pvt *p = pvt;
2386 int x = analogsub_to_dahdisub(sub);
2387
2388 return conf_add(p, &p->subs[x], x, 0);
2389}
struct stasis_forward * sub
Definition: res_corosync.c:240

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

◆ my_conf_del()

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

Definition at line 2373 of file chan_dahdi.c.

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

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

◆ my_confmute()

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

Definition at line 2292 of file chan_dahdi.c.

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

References dahdi_confmute().

◆ my_dahdi_write()

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

Definition at line 9319 of file chan_dahdi.c.

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

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

Referenced by dahdi_write().

◆ my_deadlock_avoidance_private()

static void my_deadlock_avoidance_private ( void *  pvt)
static

Definition at line 1973 of file chan_dahdi.c.

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

References DEADLOCK_AVOIDANCE, and dahdi_pvt::lock.

◆ my_decrease_ss_count()

static void my_decrease_ss_count ( void  )
static

◆ my_dial_digits()

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

Definition at line 2999 of file chan_dahdi.c.

3000{
3001 struct dahdi_pvt *p = pvt;
3002
3003 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
3004 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
3005 return -1;
3006 }
3007
3008 if (sub != ANALOG_SUB_REAL) {
3009 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
3010 dop->dialstr, p->channel, sub);
3011 return -1;
3012 }
3013
3014 return dahdi_dial_str(p, DAHDI_DIAL_OP_REPLACE, dop->dialstr);
3015}
@ ANALOG_DIAL_OP_REPLACE
Definition: sig_analog.h:134

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

◆ my_distinctive_ring()

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

Definition at line 1596 of file chan_dahdi.c.

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

References ast_channel_context_set(), ast_copy_string(), ast_debug, ast_hangup(), ast_log, ast_verb, buf, dahdi_pvt::context, ringContextData::contextData, dahdi_get_event(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, distinctiveringaftercid, dahdi_pvt::drings, errno, event2str(), dahdi_pvt::inalarm, analog_pvt::inalarm, LOG_WARNING, NULL, distRingData::range, distRingData::ring, RING_PATTERNS, dahdi_distRings::ringContext, dahdi_distRings::ringnum, analog_pvt::ringt, analog_pvt::ringt_base, S_OR, dahdi_pvt::sig_pvt, and dahdi_pvt::subs.

◆ my_dsp_reset_and_flush_digits()

static int my_dsp_reset_and_flush_digits ( void *  pvt)
static

Definition at line 1821 of file chan_dahdi.c.

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

References ast_dsp_digitreset(), and dahdi_pvt::dsp.

◆ my_dsp_set_digitmode()

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

Definition at line 1830 of file chan_dahdi.c.

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

References ANALOG_DIGITMODE_DTMF, ANALOG_DIGITMODE_MF, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_digitmode(), ast_log, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, dahdi_pvt::hardwaredtmf, LOG_ERROR, and NULL.

◆ my_flash()

static int my_flash ( void *  pvt)
static

Definition at line 2844 of file chan_dahdi.c.

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

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

◆ my_get_and_handle_alarms()

static void my_get_and_handle_alarms ( void *  pvt)
static

Definition at line 2097 of file chan_dahdi.c.

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

References get_alarms(), and handle_alarms().

◆ my_get_callerid()

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

Definition at line 1499 of file chan_dahdi.c.

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

References ANALOG_EVENT_NONE, ANALOG_MAX_CID, ast_channel_caller(), ast_channel_redirecting(), ast_copy_string(), ast_debug, AST_LAW, ast_log, ast_party_caller_free(), ast_party_caller_set(), ast_party_caller_set_init(), AST_PRES_RESTRICTED, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_UNSCREENED, ast_redirecting_reason_name(), buf, callerid_feed(), callerid_feed_jp(), callerid_get_with_redirecting(), CID_PRIVATE_NUMBER, CID_QUALIFIER, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, CID_UNKNOWN_NUMBER, ast_party_redirecting_reason::code, dahdi_pvt::cs, dahdi_get_event(), dahdievent_to_analogevent(), dahdi_subchannel::dfd, errno, ast_channel::flags, ast_party_caller::id, LOG_WARNING, name, ast_party_id::name, NULL, ast_party_id::number, pbx_builtin_setvar_helper(), ast_party_name::presentation, ast_party_number::presentation, ast_party_redirecting::reason, ast_channel::redirecting, analog_pvt::ringt, dahdi_pvt::sig_pvt, analog_pvt::ss_astchan, SUB_REAL, and dahdi_pvt::subs.

◆ my_get_event()

static int my_get_event ( void *  pvt)
static

Definition at line 2780 of file chan_dahdi.c.

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

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

◆ my_get_orig_dialstring()

static const char * my_get_orig_dialstring ( void *  pvt)
static

Definition at line 2311 of file chan_dahdi.c.

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

References dahdi_pvt::dialstring.

◆ my_get_sigpvt_bridged_channel()

static void * my_get_sigpvt_bridged_channel ( struct ast_channel chan)
static

Definition at line 2106 of file chan_dahdi.c.

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

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

◆ my_get_sub_fd()

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

Definition at line 2120 of file chan_dahdi.c.

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

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

◆ my_getsigstr()

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

Definition at line 9850 of file chan_dahdi.c.

9851{
9852 char c;
9853
9854 *str = 0; /* start with empty output buffer */
9855 for (;;)
9856 {
9857 /* Wait for the first digit (up to specified ms). */
9858 c = ast_waitfordigit(chan, ms);
9859 /* if timeout, hangup or error, return as such */
9860 if (c < 1)
9861 return c;
9862 *str++ = c;
9863 *str = 0;
9864 if (strchr(term, c))
9865 return 1;
9866 }
9867}
const char * str
Definition: app_jack.c:150

References ast_waitfordigit(), c, and str.

Referenced by analog_ss_thread().

◆ my_handle_dtmf()

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

Definition at line 1887 of file chan_dahdi.c.

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

References analogsub_to_dahdisub(), ast_async_goto(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_verb, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::callprogress, CALLPROGRESS_FAX, dahdi_confmute(), dahdi_subchannel::dfd, dahdi_pvt::dsp, dahdi_pvt::dsp_features, errno, dahdi_subchannel::f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxhandled, ast_frame::frametype, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, NULL, pbx_builtin_setvar_helper(), S_COR, ast_frame::subclass, dahdi_pvt::subs, and dahdi_pvt::usefaxbuffers.

◆ my_handle_notify_message()

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

Definition at line 3638 of file chan_dahdi.c.

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

References ANALOG_EVENT_NEONMWI_ACTIVE, ANALOG_EVENT_NEONMWI_INACTIVE, ast_hangup(), ast_log, dahdi_pvt::channel, CID_MSGWAITING, CID_NOMSGWAITING, LOG_NOTICE, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, and notify_message().

Referenced by analog_ss_thread().

◆ my_hangup_polarityswitch()

static void my_hangup_polarityswitch ( void *  pvt)
static

Definition at line 2896 of file chan_dahdi.c.

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

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

◆ my_has_voicemail()

static int my_has_voicemail ( void *  pvt)
static

Definition at line 2659 of file chan_dahdi.c.

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

References has_voicemail().

◆ my_have_progressdetect()

static int my_have_progressdetect ( void *  pvt)
static

Definition at line 3660 of file chan_dahdi.c.

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

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

◆ my_increase_ss_count()

static void my_increase_ss_count ( void  )
static

◆ my_is_dialing()

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

Definition at line 3028 of file chan_dahdi.c.

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

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

◆ my_is_off_hook()

static int my_is_off_hook ( void *  pvt)
static

Definition at line 2794 of file chan_dahdi.c.

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

References ast_log, dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_hangup(), and do_monitor().

◆ my_lock_private()

static void my_lock_private ( void *  pvt)
static

Definition at line 1961 of file chan_dahdi.c.

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

References ast_mutex_lock, and dahdi_pvt::lock.

◆ my_new_analog_ast_channel()

static struct ast_channel * my_new_analog_ast_channel ( void *  pvt,
int  state,
int  startpbx,
enum analog_sub  sub,
const struct ast_channel requestor 
)
static

Definition at line 2493 of file chan_dahdi.c.

2494{
2495 ast_callid callid = 0;
2496 int callid_created = ast_callid_threadstorage_auto(&callid);
2497 struct dahdi_pvt *p = pvt;
2498 int dsub = analogsub_to_dahdisub(sub);
2499
2500 return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, NULL, requestor, callid, callid_created);
2501}
static struct ast_channel * dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid, int callid_created)
Definition: chan_dahdi.c:9594

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

◆ my_off_hook()

static int my_off_hook ( void *  pvt)
static

Definition at line 2853 of file chan_dahdi.c.

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

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

Referenced by dahdi_hangup().

◆ my_on_hook()

static int my_on_hook ( void *  pvt)
static

Definition at line 3044 of file chan_dahdi.c.

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

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

◆ my_play_tone()

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

Definition at line 2666 of file chan_dahdi.c.

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

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

Referenced by dahdi_hangup().

◆ my_ring()

static int my_ring ( void *  pvt)
static

Definition at line 2837 of file chan_dahdi.c.

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

References dahdi_ring_phone().

◆ my_send_callerid()

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

Definition at line 1768 of file chan_dahdi.c.

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

References ast_callerid_callwaiting_full_generate(), ast_callerid_full_generate(), ast_debug, ast_free, AST_LAW, ast_log, ast_malloc, ast_party_id_presentation(), ast_verb, analog_pvt::call_qualifier, analog_pvt::caller, dahdi_pvt::callwaitcas, dahdi_pvt::cid_suppress_expire, CID_TYPE_MDMF, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, ast_party_caller::id, LOG_WARNING, MAX_CALLERID_SIZE, ast_party_id::name, NULL, ast_party_id::number, READ_SIZE, analog_pvt::redirecting_reason, send_callerid(), dahdi_pvt::sig_pvt, ast_party_name::str, and ast_party_number::str.

◆ my_set_alarm()

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

Definition at line 2146 of file chan_dahdi.c.

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

References dahdi_pvt::inalarm.

◆ my_set_cadence()

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

Definition at line 2127 of file chan_dahdi.c.

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

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

◆ my_set_callwaiting()

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

Definition at line 2276 of file chan_dahdi.c.

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

References dahdi_pvt::callwaiting.

◆ my_set_confirmanswer()

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

Definition at line 2260 of file chan_dahdi.c.

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

References dahdi_pvt::confirmanswer.

◆ my_set_dialing()

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

Definition at line 2153 of file chan_dahdi.c.

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

References dahdi_pvt::dialing.

◆ my_set_echocanceller()

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

Definition at line 2823 of file chan_dahdi.c.

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

References dahdi_ec_disable(), and dahdi_ec_enable().

◆ my_set_inthreeway()

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

Definition at line 2087 of file chan_dahdi.c.

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

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

◆ my_set_linear_mode()

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

Definition at line 2075 of file chan_dahdi.c.

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

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

◆ my_set_needringing()

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

Definition at line 2859 of file chan_dahdi.c.

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

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

◆ my_set_new_owner()

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

Definition at line 2304 of file chan_dahdi.c.

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

References dahdi_pvt::owner.

◆ my_set_outgoing()

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

Definition at line 2160 of file chan_dahdi.c.

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

References dahdi_pvt::outgoing.

◆ my_set_polarity()

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

Definition at line 2865 of file chan_dahdi.c.

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

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

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

◆ my_set_pulsedial()

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

Definition at line 2298 of file chan_dahdi.c.

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

References dahdi_pvt::pulsedial.

◆ my_set_ringtimeout()

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

Definition at line 2203 of file chan_dahdi.c.

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

References dahdi_pvt::ringt.

◆ my_set_waitingfordt()

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

Definition at line 2209 of file chan_dahdi.c.

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

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

◆ my_start()

static int my_start ( void *  pvt)
static

Definition at line 2991 of file chan_dahdi.c.

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

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

◆ my_start_cid_detect()

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

Definition at line 1466 of file chan_dahdi.c.

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

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

◆ my_start_polarityswitch()

static void my_start_polarityswitch ( void *  pvt)
static

Definition at line 2876 of file chan_dahdi.c.

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

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

◆ my_stop_callwait()

static int my_stop_callwait ( void *  pvt)
static

Definition at line 1720 of file chan_dahdi.c.

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

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

◆ my_stop_cid_detect()

static int my_stop_cid_detect ( void *  pvt)
static

Definition at line 1483 of file chan_dahdi.c.

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

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

◆ my_swap_subchannels()

static void my_swap_subchannels ( void *  pvt,
enum analog_sub  a,
struct ast_channel ast_a,
enum analog_sub  b,
struct ast_channel ast_b 
)
static

Definition at line 2449 of file chan_dahdi.c.

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

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

◆ my_train_echocanceller()

static int my_train_echocanceller ( void *  pvt)
static

Definition at line 3019 of file chan_dahdi.c.

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

References dahdi_train_ec().

◆ my_unallocate_sub()

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

Definition at line 2641 of file chan_dahdi.c.

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

References analogsub_to_dahdisub(), and unalloc_sub().

◆ my_unlock_private()

static void my_unlock_private ( void *  pvt)
static

Definition at line 1967 of file chan_dahdi.c.

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

References ast_mutex_unlock, and dahdi_pvt::lock.

◆ my_wait_event()

static int my_wait_event ( void *  pvt)
static

Definition at line 2773 of file chan_dahdi.c.

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

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

◆ my_wink()

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

Definition at line 1871 of file chan_dahdi.c.

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

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

◆ notify_message()

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

Send MWI state change.

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

This function does two things:

1) It generates an internal Asterisk event notifying any other module that cares about MWI that the state of a mailbox has changed.

2) It runs the script specified by the mwimonitornotify option to allow some custom handling of the state change.

Definition at line 3623 of file chan_dahdi.c.

3624{
3625 char s[sizeof(mwimonitornotify) + 164];
3626
3627 if (ast_strlen_zero(mailbox)) {
3628 return;
3629 }
3630
3631 ast_publish_mwi_state(mailbox, NULL, thereornot, thereornot);
3633 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
3634 ast_safe_system(s);
3635 }
3636}
static char mwimonitornotify[PATH_MAX]
Definition: chan_dahdi.c:791
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
#define ast_publish_mwi_state(mailbox, context, new_msgs, old_msgs)
Publish a MWI state update via stasis.
Definition: mwi.h:378

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

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

◆ parse_buffers_policy()

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

Definition at line 7272 of file chan_dahdi.c.

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

References ast_log, and LOG_WARNING.

Referenced by dahdi_func_write(), and process_dahdi().

◆ parse_busy_pattern()

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

Definition at line 18516 of file chan_dahdi.c.

18517{
18518 int count_pattern = 0;
18519 int norval = 0;
18520 char *temp = NULL;
18521
18522 for (; ;) {
18523 /* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
18524 if (!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
18525 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18526 break;
18527 }
18528
18529 busy_cadence->pattern[count_pattern] = norval;
18530
18531 count_pattern++;
18532 if (count_pattern == 4) {
18533 break;
18534 }
18535
18536 temp = strchr(v->value, ',');
18537 if (temp == NULL) {
18538 break;
18539 }
18540 v->value = temp + 1;
18541 }
18542 busy_cadence->length = count_pattern;
18543
18544 if (count_pattern % 2 != 0) {
18545 /* The pattern length must be divisible by two */
18546 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18547 }
18548
18549}

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

Referenced by process_dahdi().

◆ polarity_read()

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

Definition at line 2944 of file chan_dahdi.c.

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

References fxo_pvt(), and dahdi_pvt::polarity.

◆ polarity_write()

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

Definition at line 2958 of file chan_dahdi.c.

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

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

◆ process_dahdi()

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

Definition at line 18551 of file chan_dahdi.c.

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

References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, ANALOG_DIALMODE_BOTH, ANALOG_DIALMODE_DTMF, ANALOG_DIALMODE_NONE, ANALOG_DIALMODE_PULSE, ANALOG_FIRST_DIGIT_TIMEOUT, ANALOG_INTER_DIGIT_TIMEOUT, ANALOG_MATCH_DIGIT_TIMEOUT, dahdi_pvt::ani_info_digits, dahdi_pvt::ani_timeout, dahdi_pvt::ani_wink_time, dahdi_pvt::answeronpolarityswitch, ARRAY_LEN, ast_callerid_split(), ast_cc_config_params_destroy(), ast_cc_is_config_param(), ast_cc_set_param(), ast_channel_string2amaflag(), ast_copy_string(), ast_debug, ast_false(), ast_get_group(), ast_get_namedgroups(), ast_jb_read_conf(), ast_log, AST_MAX_EXTENSION, ast_strlen_zero(), ast_true(), ast_unref_namedgroups(), ast_variable_list_replace(), ast_variable_new, ast_variables_destroy(), ast_verb, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, build_channels(), dahdi_pvt::busy_cadence, dahdi_pvt::busycount, dahdi_pvt::busydetect, c, cadences, dahdi_pvt::calledsubscriberheld, dahdi_pvt::callgroup, dahdi_pvt::callprogress, CALLPROGRESS_FAX_INCOMING, CALLPROGRESS_FAX_OUTGOING, CALLPROGRESS_PROGRESS, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_pvt::cc_params, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_rxgain, CID_SIG_BELL, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, CID_START_POLARITY_IN, CID_START_RING, dahdi_pvt::cid_tag, cidrings, dahdi_pvt::context, ringContextData::contextData, copy(), dahdi_chan_conf_default(), DAHDI_CHAN_MAPPING_LOGICAL, DAHDI_CHAN_MAPPING_PHYSICAL, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_NONE, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pvt::dahditrcallerid, DEFAULT_DIALTONE_DETECT_TIMEOUT, defaultcic, defaultozz, dahdi_pvt::description, dahdi_pvt::destroy, dahdi_pvt::dialmode, dahdi_pvt::dialtone_detect, distinctiveringaftercid, dahdi_pvt::drings, DSP_DIGITMODE_RELAXDTMF, dtmfcid_level, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echotraining, errno, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxdetect_timeout, dahdi_pvt::firstdigit_timeout, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, has_pseudo, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pvt::hwrxgain, dahdi_pvt::hwrxgain_enabled, dahdi_pvt::hwtxgain, dahdi_pvt::hwtxgain_enabled, iflist, dahdi_chan_conf::ignore_failed_channels, dahdi_pvt::immediate, dahdi_pvt::immediatering, dahdi_pvt::interdigit_timeout, dahdi_chan_conf::is_sig_auto, dahdi_pvt::language, dahdi_pvt::lastnumredial, ast_variable::lineno, LINKSET_FLAG_AUTOACM, LINKSET_FLAG_DEFAULTECHOCONTROL, LINKSET_FLAG_EXPLICITACM, LINKSET_FLAG_INITIALHWBLO, LINKSET_FLAG_USEECHOCONTROL, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::manages_span_alarms, dahdi_pvt::matchdigit_timeout, mkintf(), dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, mwilevel, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, mwimonitornotify, mwisend_rpas, ast_variable::name, dahdi_pvt::named_callgroups, dahdi_pvt::named_pickupgroups, dahdi_pvt::next, ast_variable::next, NULL, num_cadence, NUM_CADENCE_MAX, NUM_SPANS, numbufs, options, dahdi_pvt::outsigmod, dahdi_pvt::parkinglot, parse_buffers_policy(), parse_busy_pattern(), dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_echocancel(), progzone, dahdi_pvt::pulse, dahdi_pvt::radio, distRingData::range, READ_SIZE, reload(), dahdi_pvt::reoriginate, report_alarms, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, ringt_base, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, SIG_PRI_AOC_GRANT_D, SIG_PRI_AOC_GRANT_E, SIG_PRI_AOC_GRANT_S, SIG_PRI_COLP_BLOCK, SIG_PRI_COLP_CONNECT, SIG_PRI_COLP_UPDATE, SIG_PRI_MOH_SIGNALING_MOH, SIG_PRI_MOH_SIGNALING_NOTIFY, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, SIG_SS7, dahdi_chan_conf::smdi_port, dahdi_pvt::span, SS7_NAI_DYNAMIC, strcasestr(), dahdi_pvt::stripmsd, strsep(), dahdi_pvt::threewaycalling, dahdi_pvt::threewaysilenthold, timer, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txdrc, dahdi_pvt::txgain, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, usedistinctiveringdetection, dahdi_pvt::usefaxbuffers, user_has_defined_cadences, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

Referenced by setup_dahdi_int().

◆ process_echocancel()

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

Definition at line 18379 of file chan_dahdi.c.

18380{
18381 char *parse = ast_strdupa(data);
18382 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
18383 unsigned int param_count;
18384 unsigned int x;
18385
18386 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
18387 return;
18388
18389 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
18390
18391 /* first parameter is tap length, process it here */
18392
18393 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
18394
18395 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
18396 confp->chan.echocancel.head.tap_length = x;
18397 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
18398 confp->chan.echocancel.head.tap_length = 128;
18399
18400 /* now process any remaining parameters */
18401
18402 for (x = 1; x < param_count; x++) {
18403 struct {
18404 char *name;
18405 char *value;
18406 } param;
18407
18408 if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
18409 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
18410 continue;
18411 }
18412
18413 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
18414 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
18415 continue;
18416 }
18417
18418 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
18419
18420 if (param.value) {
18421 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
18422 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
18423 continue;
18424 }
18425 }
18426 confp->chan.echocancel.head.param_count++;
18427 }
18428}
#define ast_app_separate_args(a, b, c, d)

References ARRAY_LEN, ast_app_separate_args, ast_log, ast_strdupa, ast_strlen_zero(), ast_true(), dahdi_chan_conf::chan, dahdi_pvt::echocancel, dahdi_pvt::head, LOG_WARNING, name, dahdi_pvt::params, and value.

Referenced by process_dahdi().

◆ publish_channel_alarm()

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

Definition at line 7778 of file chan_dahdi.c.

7779{
7780 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7781 RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
7782 if (!dahdi_chan) {
7783 return;
7784 }
7785
7786 ast_str_set(&dahdi_chan, 0, "%d", channel);
7787 body = ast_json_pack("{s: s, s: s}",
7788 "DAHDIChannel", ast_str_buffer(dahdi_chan),
7789 "Alarm", alarm_txt);
7790 if (!body) {
7791 return;
7792 }
7793
7795}
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
Definition: manager.c:638
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612

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

Referenced by handle_alarms().

◆ publish_channel_alarm_clear()

static void publish_channel_alarm_clear ( int  channel)
static

Definition at line 3835 of file chan_dahdi.c.

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

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

Referenced by handle_clear_alarms().

◆ publish_dahdichannel()

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

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

Definition at line 2011 of file chan_dahdi.c.

2012{
2013 RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
2014
2015 ast_assert(dahdi_channel != NULL);
2016
2017 blob = ast_json_pack("{s: I, s: i, s: s}",
2018 "group", (ast_json_int_t)group,
2019 "span", span,
2020 "channel", dahdi_channel);
2021 if (!blob) {
2022 return;
2023 }
2024
2025 ast_channel_lock(chan);
2026 ast_channel_publish_blob(chan, dahdichannel_type(), blob);
2027 ast_channel_unlock(chan);
2028}
void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message.
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition: json.h:87
#define ast_assert(a)
Definition: utils.h:739

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

Referenced by dahdi_ami_channel_event().

◆ publish_dnd_state()

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

Definition at line 9887 of file chan_dahdi.c.

9888{
9889 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
9890 RAII_VAR(struct ast_str *, dahdichan, ast_str_create(32), ast_free);
9891 if (!dahdichan) {
9892 return;
9893 }
9894
9895 ast_str_set(&dahdichan, 0, "%d", channel);
9896
9897 body = ast_json_pack("{s: s, s: s}",
9898 "DAHDIChannel", ast_str_buffer(dahdichan),
9899 "Status", status);
9900 if (!body) {
9901 return;
9902 }
9903
9905}
jack_status_t status
Definition: app_jack.c:149

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

Referenced by dahdi_dnd().

◆ publish_span_alarm()

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

Definition at line 7764 of file chan_dahdi.c.

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

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

Referenced by handle_alarms().

◆ publish_span_alarm_clear()

static void publish_span_alarm_clear ( int  span)
static

Definition at line 3853 of file chan_dahdi.c.

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

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

Referenced by handle_clear_alarms().

◆ release_doomed_pris()

static void release_doomed_pris ( void  )
static

Definition at line 1353 of file chan_dahdi.c.

1354{
1355#ifdef HAVE_PRI
1356 struct doomed_pri *entry;
1357
1358 AST_LIST_LOCK(&doomed_pris);
1359 while ((entry = AST_LIST_REMOVE_HEAD(&doomed_pris, list))) {
1360 /* The span destruction must be done with this lock not held */
1361 AST_LIST_UNLOCK(&doomed_pris);
1362 ast_debug(4, "Destroying span %d from doomed queue.\n",
1363 entry->pri->span);
1364 pri_destroy_span(entry->pri);
1365 ast_free(entry);
1366 AST_LIST_LOCK(&doomed_pris);
1367 }
1368 AST_LIST_UNLOCK(&doomed_pris);
1369#endif
1370}
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140

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

Referenced by do_monitor().

◆ reload()

static int reload ( void  )
static

Definition at line 20591 of file chan_dahdi.c.

20592{
20593 int res = 0;
20594
20595 res = setup_dahdi(1);
20596 if (res) {
20597 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
20598 return -1;
20599 }
20600 return 0;
20601}

References ast_log, LOG_WARNING, and setup_dahdi().

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

◆ reset_conf()

static int reset_conf ( struct dahdi_pvt p)
static

Definition at line 4899 of file chan_dahdi.c.

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

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

Referenced by dahdi_hangup(), and my_all_subchannels_hungup().

◆ restart_monitor()

static int restart_monitor ( void  )
static

Definition at line 12246 of file chan_dahdi.c.

12247{
12248 /* If we're supposed to be stopped -- stay stopped */
12250 return 0;
12252 if (monitor_thread == pthread_self()) {
12254 ast_log(LOG_WARNING, "Cannot kill myself\n");
12255 return -1;
12256 }
12258 /* Wake up the thread */
12259 pthread_kill(monitor_thread, SIGURG);
12260 } else {
12261 /* Start a new monitor */
12264 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12265 return -1;
12266 }
12267 }
12269 return 0;
12270}
static void * do_monitor(void *data)
Definition: chan_dahdi.c:11932

References ast_log, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, LOG_WARNING, monitor_thread, monlock, and NULL.

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

◆ restore_conference()

static int restore_conference ( struct dahdi_pvt p)
static

Definition at line 5332 of file chan_dahdi.c.

5333{
5334 int res;
5335 if (p->saveconf.confmode) {
5336 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
5337 p->saveconf.confmode = 0;
5338 if (res) {
5339 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
5340 return -1;
5341 }
5342 ast_debug(1, "Restored conferencing\n");
5343 }
5344 return 0;
5345}
struct dahdi_confinfo saveconf
Definition: chan_dahdi.h:132

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

Referenced by dahdi_handle_event(), dahdi_read(), handle_init_event(), my_cancel_cidspill(), and send_callerid().

◆ restore_gains()

static int restore_gains ( struct dahdi_pvt p)
static

Definition at line 5239 of file chan_dahdi.c.

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

References ast_log, dahdi_subchannel::dfd, errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::txdrc, and dahdi_pvt::txgain.

Referenced by analog_ss_thread(), dahdi_hangup(), mwi_thread(), and my_stop_cid_detect().

◆ revert_fax_buffers()

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

Definition at line 6298 of file chan_dahdi.c.

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

References ast_channel_name(), ast_log, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_hangup().

◆ save_conference()

static int save_conference ( struct dahdi_pvt p)
static

Definition at line 5306 of file chan_dahdi.c.

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

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

Referenced by dahdi_callwait(), dahdi_handle_event(), and my_callwait().

◆ send_callerid()

static int send_callerid ( struct dahdi_pvt p)
static

Definition at line 5393 of file chan_dahdi.c.

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

References ast_debug, ast_free, ast_log, dahdi_pvt::callwaitcas, CALLWAITING_SUPPRESS_SAMPLES, dahdi_pvt::cid_suppress_expire, CIDCW_EXPIRE_SAMPLES, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_setlinear(), dahdi_subchannel::dfd, errno, dahdi_subchannel::linear, LOG_WARNING, NULL, restore_conference(), SUB_REAL, and dahdi_pvt::subs.

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

◆ send_cwcidspill()

static int send_cwcidspill ( struct dahdi_pvt p)
static

Definition at line 5347 of file chan_dahdi.c.

5348{
5349 p->callwaitcas = 0;
5350 p->cidcwexpire = 0;
5351 p->cid_suppress_expire = 0;
5353 return -1;
5355 /* Make sure we account for the end */
5356 p->cidlen += READ_SIZE * 4;
5357 p->cidpos = 0;
5358 send_callerid(p);
5359 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
5360 return 0;
5361}
int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)
Definition: callerid.c:1242
char callwait_num[AST_MAX_EXTENSION]
Call waiting number.
Definition: chan_dahdi.h:543
char callwait_name[AST_MAX_EXTENSION]
Call waiting name.
Definition: chan_dahdi.h:545

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

Referenced by dahdi_handle_dtmf().

◆ set_actual_gain()

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

Definition at line 5220 of file chan_dahdi.c.

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

References set_actual_rxgain(), and set_actual_txgain().

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

◆ set_actual_rxgain()

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

Definition at line 5203 of file chan_dahdi.c.

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

References ast_debug, errno, and fill_rxgain().

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

◆ set_actual_txgain()

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

Definition at line 5186 of file chan_dahdi.c.

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

References ast_debug, errno, and fill_txgain().

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

◆ set_hwgain()

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

Definition at line 5058 of file chan_dahdi.c.

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

Referenced by dahdi_set_hwgain(), and mkintf().

◆ setup_dahdi()

static int setup_dahdi ( int  reload)
static

Definition at line 20332 of file chan_dahdi.c.

20333{
20334 int res;
20335 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
20336 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
20338
20339 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
20340 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
20341 } else {
20342 res = -1;
20343 }
20346 ast_cc_config_params_destroy(conf.chan.cc_params);
20347
20348 return res;
20349}

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

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

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

Referenced by dahdi_create_channel_range(), and setup_dahdi().

◆ sigtype_to_signalling()

static int sigtype_to_signalling ( int  sigtype)
static

Definition at line 12552 of file chan_dahdi.c.

12553{
12554 return sigtype;
12555}
enum analog_sigtype sigtype
Definition: sig_analog.c:69

References sigtype.

Referenced by mkintf().

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL()

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( dahdichannel_type  ,
to_ami = dahdichannel_to_ami 
)

◆ swap_subs()

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

Definition at line 4388 of file chan_dahdi.c.

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

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

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

◆ unalloc_sub()

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

Definition at line 4534 of file chan_dahdi.c.

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

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

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

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 18302 of file chan_dahdi.c.

18303{
18304#if defined(HAVE_PRI) || defined(HAVE_SS7)
18305 int y;
18306#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18307#ifdef HAVE_PRI
18308 for (y = 0; y < NUM_SPANS; y++)
18309 ast_mutex_destroy(&pris[y].pri.lock);
18310#endif
18311#if defined(HAVE_SS7)
18312 for (y = 0; y < NUM_SPANS; y++)
18313 ast_mutex_destroy(&linksets[y].ss7.lock);
18314#endif /* defined(HAVE_SS7) */
18315 return __unload_module();
18316}

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

◆ wakeup_sub()

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

Definition at line 3810 of file chan_dahdi.c.

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

References a, ast_channel_unlock, ast_null_frame, ast_queue_frame(), dahdi_lock_sub_owner(), dahdi_subchannel::owner, and dahdi_pvt::subs.

Referenced by my_swap_subchannels(), and swap_subs().

Variable Documentation

◆ __mod_info

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

Definition at line 20615 of file chan_dahdi.c.

◆ alarm

int alarm

Definition at line 4690 of file chan_dahdi.c.

Referenced by alarm2str().

◆ 

struct { ... } alarms[]

Referenced by alarm2str().

◆ analog_callbacks

struct analog_callback analog_callbacks

Global analog callbacks to the upper layer.

Definition at line 3686 of file chan_dahdi.c.

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

◆ AS_RP_cadence

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

Definition at line 779 of file chan_dahdi.c.

Referenced by mwi_send_process_buffer().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 20615 of file chan_dahdi.c.

◆ cadences

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
static

◆ cidrings

int cidrings[NUM_CADENCE_MAX]
static

cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.

Definition at line 771 of file chan_dahdi.c.

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

◆ config

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

Definition at line 739 of file chan_dahdi.c.

Referenced by setup_dahdi_int().

◆ dahdi_cli

struct ast_cli_entry dahdi_cli[]
static

Definition at line 16801 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

◆ dahdi_tech

struct ast_channel_tech dahdi_tech
static

◆ default_jbconf

struct ast_jb_conf default_jbconf
static

Global jitterbuffer configuration - by default, jb is disabled

Note
Values shown here match the defaults shown in chan_dahdi.conf.sample

Definition at line 688 of file chan_dahdi.c.

Referenced by setup_dahdi_int().

◆ defaultcic

char defaultcic[64] = ""
static

Definition at line 787 of file chan_dahdi.c.

Referenced by process_dahdi().

◆ defaultozz

char defaultozz[64] = ""
static

Definition at line 788 of file chan_dahdi.c.

Referenced by process_dahdi().

◆ distinctiveringaftercid

int distinctiveringaftercid = 0
static

Definition at line 799 of file chan_dahdi.c.

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

◆ dtmfcid_level

int dtmfcid_level = 256
static

Definition at line 804 of file chan_dahdi.c.

Referenced by do_monitor(), and process_dahdi().

◆ events

const char* const events[]
static

Definition at line 4667 of file chan_dahdi.c.

Referenced by event2str().

◆ global_jbconf

struct ast_jb_conf global_jbconf
static

Definition at line 696 of file chan_dahdi.c.

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

◆ has_pseudo

int has_pseudo
static

Definition at line 758 of file chan_dahdi.c.

Referenced by build_channels(), and process_dahdi().

◆ ifcount

int ifcount = 0
static

Definition at line 819 of file chan_dahdi.c.

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

◆ ifend

struct dahdi_pvt* ifend = NULL
static

Main interface list end

Definition at line 993 of file chan_dahdi.c.

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

◆ iflist

struct dahdi_pvt* iflist = NULL
static

◆ iflock

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

◆ lbostr

const char* const lbostr[]
static

Definition at line 675 of file chan_dahdi.c.

Referenced by action_dahdishowstatus(), and dahdi_show_status().

◆ monitor_thread

pthread_t monitor_thread = AST_PTHREADT_NULL
static

This is the thread for the monitor which checks for input on the channels which are not currently in use.

Definition at line 831 of file chan_dahdi.c.

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

◆ monlock

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

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

Definition at line 827 of file chan_dahdi.c.

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

◆ mwilevel

int mwilevel = 512
static

Definition at line 803 of file chan_dahdi.c.

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

◆ mwimonitornotify

char mwimonitornotify[PATH_MAX] = ""
static

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

Definition at line 791 of file chan_dahdi.c.

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

◆ mwisend_rpas

int mwisend_rpas = 0
static

Definition at line 793 of file chan_dahdi.c.

Referenced by mwi_send_init(), and process_dahdi().

◆ name

char* name

◆ num_cadence

int num_cadence = 4
static

Definition at line 755 of file chan_dahdi.c.

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

◆ num_restart_pending

int num_restart_pending = 0
static

◆ numbufs

int numbufs = 4
static

Definition at line 801 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default(), and process_dahdi().

◆ polarity_function

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

Definition at line 2985 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

◆ progzone

char progzone[10] = ""
static

Definition at line 796 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

◆ report_alarms

int report_alarms = REPORT_CHANNEL_ALARMS
static

Definition at line 808 of file chan_dahdi.c.

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

◆ restart_lock

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

Definition at line 834 of file chan_dahdi.c.

Referenced by dahdi_restart().

◆ ringt_base

int ringt_base = DEFAULT_RINGT
static

Configured ring timeout base.

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

Definition at line 881 of file chan_dahdi.c.

Referenced by mkintf(), and process_dahdi().

◆ round_robin

struct dahdi_pvt* round_robin[64]
static

Round robin search locations.

Definition at line 3760 of file chan_dahdi.c.

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

◆ ss_thread_complete

ast_cond_t ss_thread_complete
static

◆ ss_thread_count

int ss_thread_count = 0
static

◆ ss_thread_lock

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

◆ subnames

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

Definition at line 986 of file chan_dahdi.c.

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

◆ tdesc

const char tdesc[] = "DAHDI Telephony"
static

Definition at line 718 of file chan_dahdi.c.

◆ usedistinctiveringdetection

int usedistinctiveringdetection = 0
static

Definition at line 798 of file chan_dahdi.c.

Referenced by mkintf(), and process_dahdi().

◆ user_has_defined_cadences

int user_has_defined_cadences = 0
static

Definition at line 756 of file chan_dahdi.c.

Referenced by process_dahdi().